7

Google C++ スタイル ガイドの名前空間セクションには、「ヘッダー ファイルで名前のない名前空間を使用すると、C++ One Definition Rule (ODR) に違反する可能性があります」と記載されています。

実装ファイルで名前のない名前空間を使用しないと ODR 違反が発生する理由は理解できますが、ヘッダーで使用するとどのように発生するかはわかりませ。これがどのように違反を引き起こす可能性がありますか?

4

2 に答える 2

7

その理由は、匿名の名前空間で実際に何かを使用すると、未定義の動作が発生するリスクがあるためです。例えば:

namespace {
double const pi = 3.14159;
}

inline double twoPiR( double r ) { return 2.0 * pi * r; }

インライン関数 (およびクラス、テンプレート、および複数の翻訳単位で定義する必要があるその他のもの) の規則は、トークンが同一でなければならず (マクロをヒットしない限り、通常はそうです)、すべてのシンボルが同一にバインドされなければならないということです。 . この場合、各翻訳単位には の個別のインスタンスがpiあるため、piintwoPiRは各翻訳単位の異なるエンティティにバインドされます。(いくつかの例外がありますが、それらはすべて整数式を含みます。)

もちろん、匿名の名前空間がなくても、ここでは未定義の動作になります (const既定では内部リンケージを意味するため) が、基本原則は保持されます。名前のない名前空間 (またはヘッダーで定義された任意の const オブジェクト) 内の何かをヘッダーで使用すると、未定義の動作が発生する可能性があります。それが実際の問題であるかどうかによって異なりますがpi、上記の のアドレスに実際に関係するものはすべて問題を引き起こします。(ここで「本当に」と言ったのは、アドレスや参照が正式に使用される場合が多いためですが、実際には、インライン展開すると、実際に使用される値になります。もちろん、トークン3.141593.14159 どこにでもあります。が表示されます。)

于 2014-05-14T11:32:00.973 に答える
2

test.h で

namespace {
  int x;
}

namespace{
  int x;
}

そのヘッダー ファイルを任意のソース ファイルに含めると、ODR 違反が発生します。これは、xが 2 回定義されているためです。これは、コンパイラによって名前のない名前空間に一意の識別子が与えられ、翻訳単位内の名前のない名前空間のすべての出現箇所に同じ識別子が与えられるために発生します。言い換えると、すべての TU には名前のない名前空間が 1 つしかありません。

于 2014-05-14T10:39:54.690 に答える