web-dev-qa-db-ja.com

C ++の静的変数

ヘッダーファイルの静的変数とクラスで宣言された変数の違いを知りたいです。ヘッダーファイルで静的変数が宣言されている場合、そのスコープは.hファイルまたはすべてのユニットに限定されます。また、一般に静的変数は、クラスで宣言されたときに.cppファイルで初期化されますか?つまり、静的変数のスコープは2コンパイル単位に制限されるということですか?

61
brett

質問に順不同で答えるとすみませんが、この方法を理解しやすくなります。

ヘッダーファイルで静的変数が宣言されている場合、そのスコープは.hファイルまたはすべてのユニットに限定されます。

「ヘッダーファイルのスコープ」などはありません。ヘッダーファイルは、ソースファイルにincludedを取得します。翻訳単位は、ヘッダーファイルのテキストを含むソースファイルを含むです。ヘッダーファイルに書き込むものはすべて、インクルードソースファイルにcopiedを取得します。

そのため、ヘッダーファイルで宣言された静的変数は、個々のソースファイルの静的変数に似ています。

このように変数staticを宣言すると、内部リンケージを意味するため、すべての翻訳単位#includeingヘッダーファイルは、ownindividual変数(翻訳単位の外部からは見えません)を取得します。これは通常、あなたが望むものではありません。

ヘッダーファイルの静的変数とクラスで宣言された変数の違いを知りたいです。

クラス宣言では、staticは、クラスのすべてのインスタンスshareこのメンバー変数を意味します。つまり、このタイプのオブジェクトは何百もあるかもしれませんが、これらのオブジェクトの1つがstatic(または「クラス」)変数を参照するときは常に、すべてのオブジェクトで同じ値になります。 「クラスグローバル」と考えることができます。

また、通常、静的変数は、クラスで宣言されたときに.cppファイルで初期化されます。

はい、one(およびoneのみ)変換ユニットはクラスを初期化する必要があります変数。

つまり、静的変数のスコープは2コンパイル単位に制限されるということですか?

私の言ったように:

  • ヘッダーはコンパイル単位ではありません。
  • staticは、コンテキストに応じてまったく異なることを意味します。

グローバルstaticは、スコープを翻訳単位に制限します。クラスstaticは、すべてのインスタンスに対してグローバルを意味します。

これがお役に立てば幸いです。

PS:内部リンクを示すためにC++でstaticを使用するのではなく、匿名の名前空間について、Chubsdadの答えの最後の段落を確認してください。 (彼が正しいからです。;-))

86
DevSolar

ヘッダーファイルの静的変数:

'common.h'と言う

static int zzz;

この変数'zzz'には内部リンケージがあります(この同じ変数は他の翻訳単位ではアクセスできません)。 'common.h'を含む各翻訳単位には、'zzz'という名前の固有のオブジェクトがあります。

クラスの静的変数:

クラス内の静的変数は、クラスのサブオブジェクトの一部ではありません。クラスのすべてのオブジェクトによって共有される静的データメンバーのコピーは1つだけです。

$ 9.4.2/6-「名前空間スコープのクラスの静的データメンバーには外部リンケージがあります(3.5)。ローカルクラスには静的データメンバーがあってはなりません。」

'myclass.h'が持っているとしましょう

struct myclass{
   static int zzz;        // this is only a declaration
};

およびmyclass.cpp

#include "myclass.h"

int myclass::zzz = 0           // this is a definition, 
                               // should be done once and only once

および"hisclass.cpp"

#include "myclass.h"

void f(){myclass::zzz = 2;}    // myclass::zzz is always the same in any 
                               // translation unit

および"ourclass.cpp"

#include "myclass.h"
void g(){myclass::zzz = 2;}    // myclass::zzz is always the same in any 
                               // translation unit

したがって、クラスの静的メンバーは2つの翻訳単位だけに制限されません。翻訳単位のいずれかで一度だけ定義する必要があります。

注:ファイルスコープ変数を宣言するための「静的」の使用は非推奨であり、名前のない名前空間は優れた代替手段です

46
Chubsdad

クラス外のヘッダーファイルで宣言された静的変数はfile-scopedヘッダーを含むすべての.cファイル。つまり、ヘッダーファイルを含める各.cファイルで、同じ名前の変数の個別のコピーにアクセスできます。

一方、静的クラス変数はclass-scopedおよび同じ静的変数は、静的変数を持つクラスを含むヘッダーを含むすべてのコンパイル単位で使用できます。

14
Goutham