c ++スタックおよびクラス静的オブジェクト

c ++スタックおよびクラス静的オブジェクト

ヒープ、英語はヒープであり、メモリ管理のコンテキストでは、メモリが動的に割り当てられる領域を指します。このヒープは、データ構造のヒープと同じではありません。ここでのメモリは、割り当て後に手動で解放する必要があります。そうしないと、メモリリークが発生します。

C ++標準の関連概念は、無料のストレージ領域、英語は無料のストア、具体的には、メモリの割り当てと解放にnewとdeleteが使用される領域を指します一般的に、これはヒープのサブセットです。

  • newそしてdelete、操作の領域は無料の店です

  • mallocそして、free操作領域はヒープです

    しかし、newそして delete通常は基本的な使用mallocおよびfree実装するには、その自由な店もヒープです。区別の実際の意味はあまり大きくないため、この列では、特に明記されていない限り、ヒープという用語のみを使用します。

スタック、英語はスタックであり、メモリ管理のコンテキストでは、関数呼び出し中に生成されたローカル変数と呼び出しデータの領域を指します。このスタックは、データ構造のスタックの高さに似ており、どちらも「後入れ先出し」(後入れ先出しまたはLIFO)を満たします。
完全な英語であるRAIIは、Resource Acquisition Is Initializationであり、C ++の独自のリソース管理方法です。D、Ada、Rustなど、他の少数の言語もRAIIを採用していますが、主流のプログラミング言語の中で、リソース管理をRAIIに依存しているのはC ++だけです。RAIIは、スタックとデストラクタに依存して、ヒープメモリを含むすべてのリソースを管理します。

RAIIを使用すると、Javaのようなガベージコレクションメソッドを必要とせずに、C ++でメモリを効果的に管理できます。RAIIの存在は、理論的にはガベージコレクションをC ++で使用できる主な理由でもありますが、実際に普及したことはありません。次に、ヒープ、スタック、およびRAIIについて詳細に説明します。

プライベートデストラクタを宣言する

クラスがメモリを割り当てることができるの、デストラクタをプライベートとして宣言できます。

class alloc

{
public:

    alloc():

private:

   ~alloc();

};
スタックにスペースが割り当てられている場合、クラスはスコープを離れるときにスペースを解放するためにデストラクタを呼び出します。この時点では、プライベートデストラクタを呼び出すことはできません。

ヒープにスペースが割り当てられている場合、デストラクタは削除されたときにのみ呼び出されます。

c ++ランタイムメモリ割り当て

なるC / C ++と、ランタイムコンパイルされたプログラムメモリは、次のセクションに分割されている占有
1
スタック領域(スタック-自動的に割り当てられ実行解放、関数パラメータ、ローカル変数、等を記憶します。*
動作モードは、データ構造のスタックに似ています。
2 *、heap(heap-割り当てられたプログラマーによってリリースされる一般。プログラマーがリリースされない場合、プログラムはOS back *
コレクションの終わりまでに提供される場合がありますデータ構造のヒープとは異なり、割り当て方法はリンクリストに似ていることに注意してください( C ++の場合のみJavaにはGCがあり、方法は異なります)、ハハ。
3.グローバルエリア(静的エリア)(static)、グローバル変数と静的変数のストレージがまとめられ、初期化されたグローバル変数と静的変数は同じエリアにあり、初期化されていないグローバル変数と初期化されていない静的変数は別のエリアに隣接しています。-システムによってリリースされたプログラムの終了後。
4 *、リテラル定数領域-定数文字列がここに配置されます。プログラムが終了すると、システムは
5を解放します。
プログラムコード領域* — *は、関数本体のバイナリコードを格納します。

img

静的メンバー

静的メンバー変数には、次の特性があります。

  1. 静的メンバー変数は、このクラスのすべてのオブジェクトに共通です。通常のメンバー変数の場合、各クラスオブジェクトには独自のコピーがあります。静的メンバー変数は全部あります。このクラスのオブジェクトがいくつ定義されていても、静的メンバー変数のメモリは1回だけ割り当てられ、クラスのすべてのオブジェクトによって共有されます。したがって、静的データメンバーの値はすべてのオブジェクトで同じであり、その値を更新できます。
  2. 静的データメンバーはグローバルデータ領域にメモリを割り当て、このクラスのすべてのオブジェクトによって共有されるため、特定のクラスオブジェクトに属しておらず、オブジェクトのメモリを占有しません。代わりに、すべての外部のメモリを開きます。オブジェクト。クラスオブジェクトが生成されない場合そのスコープは表示されますしたがって、クラスのインスタンスがない場合、静的メンバー変数はすでに存在し、それを操作できます。

このポインタがないため、クラスオブジェクトでなくても呼び出すことができます

  1. 静的メンバー変数は、グローバルデータ領域に格納されます。静的メンバー変数のメモリ空間は、クラスが宣言されたときもオブジェクトが作成されたときも割り当てられませんが、初期化されたときに割り当てられます。

    静的メンバー変数は初期化する必要があり、クラスの外部でのみ実行できます。それ以外の場合、コンパイルは成功しますが、リンクは成功しません。例5では、ステートメントint Myclass :: Sum = 0;は、静的メンバー変数を定義および初期化することです。初期値は、初期化時に割り当てることも、割り当てないこともできます。値が割り当てられていない場合、デフォルトで初期化されます。通常は0です。静的データ領域の変数にはデフォルトの初期値があり、動的データ領域(ヒープ領域、スタック領域)の変数にはデフォルトでガベージ値があります。
  2. 静的メンバー変数は通常の静的変数と同じです。メモリはコンパイル時に静的データ領域に割り当てられ、プログラムの最後に解放されます。これは、静的メンバー変数がオブジェクトの作成時にメモリを割り当てたり、オブジェクトの破棄によってメモリを解放したりしないことを意味します。通常のメンバー変数は、オブジェクトの作成時にメモリを割り当て、オブジェクトが破棄されるとメモリを解放します。

  3. 静的データメンバーの初期化は、一般的なデータメンバーの初期化とは異なります。静的は初期化中に省略できますが、データ型が必要です。private、protected、およびpublicによって変更された静的メンバー変数は、すべてこの方法で初期化できます。静的データメンバーの初期化の形式は次のとおりです。<データ型> <クラス名> :: <静的データメンバー名> = <値>

  4. クラス1の静的メンバー変数アクセス形式:<クラスオブジェクト名>。<静的データメンバー名>

  5. クラス2の静的メンバー変数アクセス形式:<クラスタイプ名> :: <静的データメンバー名>、つまり、静的メンバーは、オブジェクトを経由せずにアクセスできます。

  6. 静的データメンバーは、通常のデータメンバーと同じパブリック、プロテクト、およびプライベートアクセスルールに従います。

  7. 静的データメンバー(つまり、パブリックのメンバー)のアクセス権が許可されている場合、静的データメンバーは上記の形式に従ってプログラムで参照できます。

  8. sizeof演算子は、静的メンバー変数を計算しません。

2.(オブジェクト指向)静的メンバー関数

静的メンバー変数と同様に、静的メンバー関数を宣言することもできます。

静的メンバー関数は、特定のクラスの特定のオブジェクトではなく、クラスにサービスを提供します。静的メンバー変数と同様に、静的メンバー関数はクラスの内部実装であり、クラス定義の一部です。通常のメンバー関数はオブジェクトに特に作用する必要がありますが、静的メンバー関数はオブジェクトに特に作用しません。**通常のメンバー関数は通常thisポインターを意味します。通常のメンバー関数は常にクラスの特定のオブジェクトに特に属するため、このポインターはクラス自体のオブジェクトを指します**。関数が呼び出されると、システムは現在のオブジェクトの開始アドレスをこのポインタに割り当てます。通常、これがデフォルトです。==関数fn()が実際にthis-> fn()==の場合。

通常の関数と比較して、静的メンバー関数はクラス自体に属し、オブジェクトには作用しません。*したがって、このポインタはありません*。特定のオブジェクトを指していないため、クラスオブジェクトに属する非静的メンバー変数と非静的メンバー関数にアクセスできません。残りの静的メンバー関数と静的メンバー変数のみを呼び出すことができます。>別の見方をすれば、静的メンバー関数と静的メンバー変数はすでに存在し、クラスがインスタンス化される前にアクセスでき、非静的メンバーは現時点ではまだ存在しないため、静的メンバーは非静的メンバーにアクセスできません。

静的メンバー関数の機能:

    1. クラスの外部に表示される関数定義では、キーワードstaticを指定できません。
    1. 静的メンバーは相互にアクセスできます。つまり、静的メンバー関数(のみ)は静的メンバー変数と静的メンバー関数にアクセスできます。
    1. 静的メンバー関数は、非静的メンバー関数および非静的メンバー変数にアクセスできません。
    1. 非静的メンバー関数は、静的メンバー関数と静的データメンバーに任意にアクセスできます。
    1. このポインターの追加のオーバーヘッドがないため、静的メンバー関数はクラスグローバル関数よりもわずかに高速です。
    1. 静的メンバー関数を呼び出すには、次の2つの方法があります。

    メンバーアクセス演算子(。)および(->)を介して、つまり、静的メンバー関数は、クラスオブジェクトまたはクラスオブジェクトへのポインターを介して呼び出されます。

    クラスを介して静的メンバー関数を直接呼び出します。<クラス名> :: <静的メンバー関数名>(<パラメーターリスト>)。つまり、静的メンバーには、オブジェクトを経由せずにアクセスできます。

3.(手順指向)静的グローバル変数

グローバル変数の前に、キーワードstaticを追加します。この変数は、静的グローバル変数として定義されます。

静的グローバル変数には、次の特性があります。

  1. 変数は、グローバルデータ領域にメモリを割り当てます。
  2. 初期化されていない静的グローバル変数は、プログラムによって自動的に0に初期化されます(自動変数の自動初期化値はランダムです)。
  3. 静的グローバル変数は、宣言されているファイル全体に表示されますが、ファイルの外部には表示されません。
  4. 静的変数には、後で説明する静的ローカル変数を含め、グローバルデータ領域にメモリが割り当てられます。完全なプログラムの場合、メモリ内の分布は次のとおりです。[コード領域] [グローバルデータ領域] [ヒープ領域] [スタック領域]、一般プログラムでnewによって生成された動的データはヒープ領域に格納され、関数は自動的にスタック領域に格納され、静的データ(関数内の静的ローカル変数も含む)はグローバルデータ領域に格納されます。自動変数は通常、関数の終了時にスペースを解放しますが、グローバルデータ領域のデータは関数の終了によりスペースを解放しません

4.(手順指向)静的ローカル変数

ローカル変数の前に、キーワードstaticを追加します。この変数は、静的ローカル変数として定義されます。

通常、変数は関数本体で定義され、プログラムがステートメントを実行するたびにスタックメモリがローカル変数に割り当てられます。ただし、プログラムが関数本体を終了すると、システムはスタックメモリを再利用し、それに応じてローカル変数が無効になります。

ただし、2つの呼び出しの間に変数の値を保存する必要がある場合があります。通常の考え方は、達成するグローバル変数を定義することです。しかし、このようにして、変数は関数自体に属さなくなり、関数によってのみ制御されなくなり、プログラムの保守に不便が生じます。

静的ローカル変数は、この問題を解決するだけです。静的ローカル変数は、スタックではなくグローバルデータ領域に格納されます。各時間の値は、次の呼び出しまで、次に新しい値が割り当てられるまで保持されます。

静的ローカル変数には、次の特性があります。

  1. 静的ローカル変数は、グローバルデータ領域にメモリを割り当てます。
  2. 静的ローカル変数は、プログラムがオブジェクトの宣言に対して実行されるときに初めて初期化されます。つまり、後続の関数呼び出しは初期化されません。
  3. 静的ローカル変数は通常、宣言の場所で初期化されます。明示的に初期化されていない場合、プログラムによって自動的に0に初期化されます。
  4. 静的ローカル変数は、プログラムが終了するまで常にグローバルデータ領域に存在します。ただし、そのスコープはローカルスコープであり、それを定義する関数またはステートメントブロックが終了すると、そのスコープは終了します。

5.(手順指向の)静的関数

関数の戻り値の型の前にstaticキーワードを追加すると、関数は静的関数として定義されます。静的関数は通常の関数とは異なり、宣言されたファイルでのみ表示でき、他のファイルでは使用できません。

静的関数を定義する利点:(静的グローバル変数と同様)

  1. 静的関数は他のファイルでは使用できません。
  2. 同じ名前の関数は、競合することなく他のファイルで定義できます。

おすすめ

転載: blog.csdn.net/ahelloyou/article/details/113508374