6

件名は主にここ ( C++ でクラス スコープ定数を宣言/定義する場所は? ) で、特にここで取り上げられています。

整数定数の場合、私が完全に理解したいのは、次の違いがあります。

//In the header
class A {
private:
static const int member = 0; //Declaration and definition
};

と:

//In the header
class A {
private:
static const int member; //Only declaration
};

//In the cpp
const int A::member = 0; //Definition

(定数の値を変更すると、1つのファイルだけを再コンパイルする必要があるという利点があることを理解しています)

副次的な質問:
たとえば、にアクセスするヘッダーで定義されたインライン メソッドではどうなりますmemberか? 単にインライン化されないのでしょうか? 極端な例として、すべてのメソッドがヘッダー ファイルでインライン メソッドとして定義され、すべての定数が cpp ファイルで定義されている場合はどうなるでしょうか。

編集:

申し訳ありません: 必要ないと思っていましたが、メンバーが静的であるという事実を見逃していました。私の質問は残りますが、コードは合法です。

4

3 に答える 3

6

質問が変更されて静的になる前のように、それが非静的メンバーである場合、コンストラクターの初期化子リストまたは (2011 年以降) メンバーの宣言でのみ初期化できます。2番目の例は形式が正しくありませんでした。

静的であり、 odr-usedの場合は定義が必要です。大まかに言えば、値だけでなくアドレスを必要とする何かを行う場合です。値のみを使用する場合は、最初の例で問題ありません。ただし、コメントが間違っていることに注意してください。これは単なる宣言であり、定義ではありません。

定義が必要な場合は、宣言または定義のどちらで値を指定するかはあなた次第です。宣言で指定すると、変数が使用されるときに値が常に使用可能になるため、最適化の範囲が広がります。定義で指定すると、カプセル化が向上し、変更された場合に再コンパイルする必要があるのは 1 つの翻訳単位のみです。

たとえば、メンバーにアクセスするヘッダーで定義されたインライン メソッドではどうなりますか? それは単にインライン化されませんか?

別の翻訳単位で定義されたデータ オブジェクトにアクセスすることで、関数がインライン化されないようにする理由はありません。

于 2013-08-09T07:22:59.930 に答える
2

考慮すべき 2 つの観点があります。つまり、可視性とアドレス指定です。

この 2 つは直交関係にあることに注意してください。実際には、変数を初期化済みとして宣言しても、変換単位で定義できるため、メモリ内に実効アドレスを持つことができます。

視認性

可視性は変数の使用に影響を与え、技術的な影響もあります。

非型テンプレート パラメーターとしてテンプレート コードで使用するには、使用時に値が表示される必要があります。また、C++11 では、これが使用上必要になる場合がありconstexprます。それ以外の場合、値を表示する必要はありません。

技術的には、目に見える値はコンパイラからの最適化をトリガーできます。たとえば、if (A::member)自明に false であるため、テストを省略できます。これは、一般に一定伝播と呼ばれます。これは良いことのように思えるかもしれませんが、一見すると重大な影響があります。ヘッダー ファイルのすべてのクライアントはこの値に依存する可能性があるため、この値を変更すると再コンパイルする必要があります。このヘッダーを共有ライブラリの一部として提供する場合、この値を変更すると ABI が壊れることになります。

アドレッシング

ここでのルールは非常に単純です。変数がアドレス指定できる場合 (ポインターまたは参照によって渡される場合)、その変数はメモリ内のどこかに常駐する必要があります。これには、1 つの翻訳単位での定義が必要です。

于 2013-08-09T08:56:49.200 に答える