繁体   English   中英

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

[英]How would use of unnamed namespaces in headers cause ODR-violations?

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

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

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

namespace {
double const pi = 3.14159;
}

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

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

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

在test.h中

namespace {
  int x;
}

namespace{
  int x;
}

在任何源文件中包含该头文件都会导致ODR违规,因为x被定义了两次。 发生这种情况是因为编译器为未命名的命名空间赋予了唯一标识符,并且翻译单元中所有出现的未命名命名空间都被赋予相同的标识符。 换句话说:每个TU最多只有一个未命名的命名空间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM