C ++で「グローバル」変数を宣言する場合、「静的」とはどういう意味ですか?
-
26-09-2019 - |
質問
解決
キーワード static
コンテキストに応じて、C ++の意味が異なります。
自由関数またはグローバル変数を宣言する場合、この単一の翻訳ユニットの外で機能が利用できないことを意味します。
// test.cpp
static int a = 1;
static void foo() {}
その翻訳ユニットが記号を含む別の翻訳ユニットにリンクされているとコンパイルの結果がある場合 a
と foo
この特定の翻訳ユニットのように、それは1つの定義ルールを破ることはありません a
と foo
それは プライベート シンボル。この使用は、名前のない名前空間によって廃止されています。
// test2.cpp
namespace {
static int a = 1;
static void foo() {}
}
関数内でローカル変数を宣言する場合、変数の寿命は、最初の呼び出しから関数まで、プログラムの最後まで拡張されることを意味します。
int foo() {
static int counter = 0;
return ++counter;
}
int main() {
for ( int i = 0; i < 10; ++i ) {
std::cout << foo() << std::endl;
}
}
前のコードでは、 counter
一度初期化されます foo
初めて呼び出されますが、変数は関数より長くなり、異なる関数呼び出しで値を保持します。前のコードには「1 2 3 4 ... 10」が印刷されます。変数が宣言されていない場合 static
その後、出力は「1 1 1 ... 1」になります。
クラスの範囲内で、 static
メンバーがクラスのメンバーであり、特定のインスタンスではなく、クラスのメンバーであることを意味します。この使用は、他の質問での使用と同等です。その特定のメンバーの使用は、特定のオブジェクトに拘束されません。
struct test {
int x;
static int y;
};
int test::y; // need to define it in one translation unit
int main() {
// test::x = 5; // !error cannot access a non-static member variable
// without an instance
test::y = 5; // ok
test t, other;
t.x = 10; // ok
t.y = 15; // ok, the standard allows calling a static member through
// an instance, but this is the same as test::y
}
この場合、メンバー x
非静的なメンバー属性であるため、別のものがあります x
クラスの各インスタンスについて。サンプルプログラムで t.x
と other.x
別の整数を参照してください。一方で y
は static
したがって、単一のインスタンスがあります test::y
プログラムで。標準で呼び出すことができても t.y
と other.y
どちらの使用も同じ変数を参照します。メンバーの方法にも同じことが言えます。それらが静的である場合、それらはクラスレベルのメソッドであり、インスタンスなしで呼び出すことができますが、それらは非静的な場合、具体的なインスタンスと a.b
また a->b
構文を使用する必要があります。
のこの使用 static
Javaで同じキーワードの使用に似ていますが、他の2つはその言語には存在しません。 JavaにはC ++には存在しないキーワードの使用が1つあります。これは、静的クラス初期剤(に囲まれたクラスレベルのコードブロックの使用です。 static { ... }
)。 Javaでは、クラスがロードされたときに1回だけのコードブロックが実行されます。 C ++の静的メンバー変数の初期化は、変数定義の初期化器で実行する必要があります。
他のヒント
これは、変数が翻訳ユニットにローカルであることを意味します(単純に配置された、単一のソースファイルに)、外部からアクセスできないことを意味します。この静的の使用は、実際には現在のC ++標準で非推奨です。代わりに、匿名の名前空間を使用することになっています。
static int x = 0;
あるべきです:
namespace {
int x = 0;
}
このようなものはかなりよく覆われているようです ここ.
しかし、言い換えるには、Cには2つの用途があります
- ファイルを定義するファイルの範囲外でグローバル変数の使用を防ぎます。
関数内のローカル変数が、関数のように承認の呼び出しを持続させることを許可します。
int getNextId(){static int id = 0; ID ++を返します。 }
C ++はこれらの両方を継承し、独自の2つの用途を追加します。
- 静的メンバー変数:クラスのすべてのインスタンスを「共有」し、クラスのインスタンスを参照せずにアクセスすることもできます。共有は間違った単語のように思えますが、本質的に私は、staticメンバー変数への参照が同じメモリの位置を参照するという結果が得られると信じています。
- 静的方法:それを定義するクラスの特定のインスタンスを参照せずに呼び出すことができる方法。
静的とは、基本的に、変数がプログラムの寿命に結び付けられていることを意味し、特定の関数またはクラスのインスタンスではありません。いつ使用する必要がありますか?しないでください。目的は何ですか?主にデータのデバッグ。
一般的に、C ++では、静的データを使用していることに気付いた場合、間違ったことをしました。適切な場合がありますが、非常にまれです。
C ++のクラスで静的が使用される場合、それは多かれ少なかれJavaで行うのと同じことを意味します。変数については、変数の1つのインスタンスがすべてのクラスと関数に存在することを意味します。これは、関数がこのポインターに暗黙的にアクセスしないことを意味します。
CおよびC ++では、静的がグローバル変数または関数に使用される場合、変数は現在のCまたはC ++ファイルでのみ参照できることを意味します。言い換えれば、コンパイラは変数または関数の再配置記号を生成してはなりません。
静的がローカル関数の変数の隣に使用される場合、変数はスコープから外れず、関数コールから関数コールまでの値を保持することを意味します。変数は、特定の関数からのみアクセスできるグローバル変数に効果的になります。
静的クラスメンバーは、クラスのオブジェクトではなく、クラス自体に関連付けられているデータと関数です。
次の例では、クラスのフレッドには静的データメンバーX_とインスタンスデータメンバーY_があります。 Fred :: X_のコピーは1つだけです。FREDオブジェクトの作成(Fredオブジェクトなしを含む)の数に関係なく、Fredオブジェクトごとに1つのY_があります。したがって、X_はクラスに関連付けられていると言われ、Y_はクラスの個々のオブジェクトに関連付けられていると言われています。同様に、クラスのFredには静的メンバー関数f()とインスタンスメンバー関数g()があります。
class Fred {
public:
static void f() throw(); <-- 1
void g() throw(); <-- 2
protected:
static int x_; <-- 3
int y_; <-- 4
};
(1)クラスに関連付けられたメンバー関数
(2)クラスの個々のオブジェクトに関連するメンバー関数
(3)クラスに関連付けられたデータメンバー
(4)クラスの個々のオブジェクトに関連付けられているデータメンバー
使用法:
作成されたクラスのインスタンスの数のトラクトを保持する場合、静的変数を使用します。たとえば、「車」クラスでは、各車のインスタンスには一意のシリアル番号(この場合は_y)があり、会社は生産された車の数(この場合は_x)を追跡したい場合があります。