6

名前空間スコープで宣言されているか、クラス/構造体/共用体内で宣言されているかに関係なく、C++は同じ特別なルールをstatic const整数型に適用するという印象を受けました。

今、私は非準拠のコンパイラから悪いことを教えられてきたと思っています。

static const int A = 1;

struct s
{
    static const int A = 1;
};

スコープの明らかな違いは別として、どのように、そしてどのようAs::A違いますか?

  • ...それらの使用法がそれらのリテラル値に置き換えられるのはいつですか?
  • ...いつ私はそれのアドレスを取ることができますか?
  • ...個別に定義する必要がある場合は?

特にC++03に興味があります。

4

2 に答える 2

6

キーワードstaticは、クラススコープと名前空間スコープで同じことを意味するわけではありません。実際、名前空間スコープでの使用は非推奨です。

クラススコープで変数を宣言する場合static、静的ストレージ期間と有効期間を持つ変数の単一インスタンスが存在することを意味します。クラス内の宣言は定義ではありません。変数を使用する場合は、1つの(そして1つだけの)変換単位で定義する必要があります。定義されていない場合、未定義の動作があります。(実際には、用途に応じて、すべてが正常に機能するか、リンカーからエラーが発生します。)宣言がconst整数型であり、初期化が含まれて いる場合、それが使用されているとは見なされないことに注意してください。定数積分式(Cスタイルの配列の次元など)を必要とするコンテキストで使用されます。最も単純で確実なことは、それをどこかに定義することです。

名前空間スコープで変数を宣言する場合、名前staticが外部ではなく内部リンクを持っていることを意味します。の有無にかかわらずstatic、宣言は定義です(したがって、プログラムに他の定義があってはなりません)。C ++ 03では、この使用は非推奨になりました。代わりに名前のない名前空間を使用してください。変数自体がconst(最上位のconst)である場合、デフォルトで内部リンケージがあるため、staticはまったく効果がないことにも注意してください。const(外部リンケージを持つ変数が必要な場合は、それをクラスメンバーにするか、明示的に定義externします。宣言だけでなく、初期化子を使用して定義します。)

于 2012-12-18T15:54:30.020 に答える
0

どのように、そしてどのようAs::A異なりますか?

最大の違いは、の宣言Aも定義であるのに対し、の宣言はそうでs::Aはないということです。「特別なルール」とはどういう意味かわかりませんstaticが、それぞれ意味が異なります。

名前空間スコープでは、オブジェクトが現在の変換ユニットの外部に表示されないように、内部リンクを提供します。static名前空間スコープの定数変数にはデフォルトで内部リンケージがあるため、ここでは冗長であることに注意してください。

クラススコープでは、クラスのインスタンス化に関係なく単一のオブジェクトが存在することを意味します。

それらの使用法がリテラル値に置き換えられるのはいつですか?

どちらも宣言に初期化子が含まれる整数定数であるため、どちらも定数式で使用でき、コンパイラーはそれらの値をコンパイル時の定数に置き換えることができます。

おそらく、より適切な質問は、いつ定義が必要かということです。

C ++ 11では、変数がodrで使用されている場合に必要です。大まかに言えば、変数の値ではなくアドレスを必要とする何かを行う場合です。

C ++ 03では、変数を使用する場合は必要だったと思いますが、診断は不要であり、その値のみを使用しても多くのコンパイラは文句を言いません。しかし、私は間違っている可能性があります。古いルールはかなり複雑で、今では忘れることができてうれしいです。

いつ私はそれのアドレスを取ることができますか?

そのためには、C++03とC++11の両方で変数に定義が必要です。定義は、変数にストレージを割り当てて、アドレスを持つようにします。

それらを個別に定義する必要がある場合は?

名前空間スコープでの変数宣言も、宣言しない限り定義externです。したがって、最初の変数に個別の定義は必要ありません。

クラススコープでの変数宣言は定義ではありません。したがって、2番目の変数は、C ++ 03で、およびodr-usedの場合はC++11で個別に定義する必要があります。

于 2012-12-18T17:05:03.620 に答える