如何在标头中使用未命名的命名空间会导致ODR违规?

boy*_*ycy 6 c++ one-definition-rule unnamed-namespace

在Google C++样式指南中,命名空间部分指出" 在头文件中使用未命名的命名空间很容易导致违反C++ One Definition Rule(ODR). "

我理解为什么不在实现文件中使用未命名的命名空间可能会导致ODR违规,但不能在标头中使用它们.这怎么会导致违规?

Jam*_*nze 5

原因是,如果您实际使用匿名命名空间中的任何内容,则存在未定义行为的风险.例如:

namespace {
double const pi = 3.14159;
}

inline double twoPiR( double r ) { return 2.0 * pi * r; }
Run Code Online (Sandbox Code Playgroud)

内联函数(以及类和模板以及必须在多个翻译单元中定义的任何其他内容)的规则是令牌必须相同(通常情况下,除非您点击某个宏),并且所有符号必须以相同方式绑定.在这种情况下,每个翻译单元都有一个单独的实例pi,因此piin twoPiR绑定到每个翻译单元中的不同实体.(有一些例外,但它们都涉及整体表达.)

当然,即使没有匿名命名空间,这也是未定义的行为(因为const默认情况下意味着内部链接),但基本原则成立.在未命名的命名空间(或标头中定义的任何const对象)中的任何内容的标头中的任何使用都可能导致未定义的行为.它是否是一个真正的问题取决于,但肯定涉及上述地址的任何事情pi都会引起问题.(我说"真的"在这里,因为有很多情况下地址或引用正式使用,但在实践中,内联扩展将导致实际使用的价值.当然,令牌3.141593.14159 无论它出现.)

  • @boycy除了它确实导致未定义的行为.参见示例:函数`twoPiR`具有未定义的行为.这肯定是Google编码指南中规则的动机(而Rakibul的答案与未命名的命名空间无关). (2认同)
  • 哎.你的回答很有意思,当然让我对这个细微差别有了更深刻的理解,以及为什么谷歌可能会制定规则,所以谢谢你.它没有回答我的问题,这不是关于谷歌的理由,而是关于ODR违规. (2认同)