如何在标头中使用未命名的命名空间会导致ODR违规? [英] How would use of unnamed namespaces in headers cause ODR-violations?
问题描述
在Google C ++样式指南中,命名空间部分
我理解为什么要使用未命名的命名空间在头文件中容易导致违反C ++ One Definition Rule(ODR)在实施文件中使用未命名的命名空间可能会导致ODR违规,但不会影响标题中的使用方式。
原因是如果你真的在匿名
命名空间中使用任何东西,你有未定义的行为风险。例如:
命名空间{
double const pi = 3.14159;
}
inline double twoPiR(double r){return 2.0 * pi * r; }
内联函数(以及类和模板以及
)的规则必须在多个翻译
单位中定义)是令牌必须是相同的(通常情况下,
,除非你敲一些宏),并且所有符号必须同样绑定
。在这种情况下,每个翻译单元都有一个单独的
实例 pi
,因此 pi
c $ c> twoPiR 绑定到每个翻译单元中不同的
实体。 (有一些例外,
,但它们都涉及整数表达式。)
当然,即使没有匿名命名空间,这将是
未定义的行为这里(因为 const
表示内部链接通过
默认),但基本原则成立。在未命名的命名空间(或
中定义的任何const对象的头)中
任何东西的头部中的任何使用都可能导致未定义的行为。不管它是
是一个真正的问题或不依赖,但肯定任何
真正涉及 pi
的地址,将导致
的问题。 (我在这里说真的,因为有很多情况
地址或引用正式使用,但在
练习中,内联展开将导致实际上使用
的值当然,令牌 3.14159
是 3.14159
,不管它出现在哪里。)
In the Google C++ Style Guide, the Namespaces section states that "Use of unnamed namespaces in header files can easily cause violations of the C++ One Definition Rule (ODR)."
I understand why not using unnamed namespaces in an implementation file can cause ODR-violations, but not how use in a header can do so. How can this cause a violation?
The reason is that if you actually use anything in the anonymous namespace, you risk undefined behavior. For example:
namespace {
double const pi = 3.14159;
}
inline double twoPiR( double r ) { return 2.0 * pi * r; }
The rule for inline functions (and classes, and templates, and
anything else which must be defined in multiple translation
units) is that the tokens must be identical (normally the case,
unless you hit some macro), and that all symbols must bind
identically. In this case, each translation unit has a separate
instance of pi
, so the pi
in twoPiR
binds to a different
entity in each translation unit. (There are a few exceptions,
but they all involve integral expressions.)
Of course, even without the anonymous namespace, this would be
undefined behavior here (since const
means internal linkage by
default), but the basic principle holds. Any use in a header of
anything in an unnamed namespace (or any const object defined in
the header) is likely to cause undefined behavior. Whether it
is a real problem or not depends, but certainly anything which
really involves the address of pi
, above, is going to cause
problems. (I say "really" here, because there are many cases
where the address or a reference is formally used, but in
practice, the inline expansion will result in the value actually
being used. And of course, the token 3.14159
is 3.14159
regardless of where it appears.)
这篇关于如何在标头中使用未命名的命名空间会导致ODR违规?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!