在标头中使用未命名的名称空间将如何导致odr违规
How would use of unnamed namespaces in headers cause ODR-violations?
在Google c++风格指南中,命名空间部分指出"在头文件中使用未命名的命名空间很容易导致违反c++单一定义规则(ODR)。"
我理解为什么不在实现文件中使用未命名的名称空间会导致odr违规,但不知道在头文件中使用如何做到这一点。这怎么可能导致违规呢?
原因是,如果您实际上在匿名中使用任何东西命名空间中,您将面临未定义行为的风险。例如:
namespace {
double const pi = 3.14159;
}
inline double twoPiR( double r ) { return 2.0 * pi * r; }
内联函数(类、模板和)的规则任何其他必须在多种翻译中定义的内容单位)是令牌必须相同(通常情况下,除非你击中了一些宏),所有的符号都必须绑定相同。在这种情况下,每个翻译单元都有一个单独的pi
的实例,所以twoPiR
中的pi
结合到不同的每个翻译单元中的实体。(也有一些例外,但是它们都包含整型表达式。)
当然,即使没有匿名命名空间,这也是这里的未定义行为(因为const
表示内部链接)默认),但基本原则是成立的。的头文件中使用中定义的const对象中的任何内容头文件)可能导致未定义的行为。它是否这是一个真正的问题或不是取决于,但肯定是什么真正涉及到pi
的地址,上面,是要引起的问题。(我在这里说"真的",因为有很多情况在正式使用地址或参考的地方,但在实际上,内联展开会得到这个值被使用。当然,令牌3.14159
是3.14159
In test.h
namespace {
int x;
}
namespace{
int x;
}
在任何源文件中包含该头文件都将违反ODR,因为x
定义了两次。这是因为编译器为未命名的命名空间提供了唯一标识符,并且翻译单元中所有未命名的命名空间都被赋予了相同的标识符。换句话说:每个TU最多有一个未命名的命名空间。
相关文章:
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 命名空间中具有.h和.cpp文件的类
- 从父命名空间重载类型
- 从类型列表中递归删除重复项会导致编译器堆空间错误 (VS2017)
- pthread_spinlock是否会导致从用户空间切换到内核空间
- 无法获取 wig %ignore 以忽略命名空间中的类,从而导致编译错误
- c++ 内联友元函数是否会导致命名空间之间的名称隐藏?
- 加载到阵列中会导致堆栈粉碎,同时有足够的空间
- C 无法解释的类“尚未声明”错误,这是由于名称空间而导致的
- Android Studio-用户名空间导致崩溃,NDK没有安装到此目录
- 由于命名空间而导致的对象实例化错误
- 包含命名空间的类模板的前向声明会导致编译错误
- 命名空间中的全局变量会导致"undefined reference to"
- 写入 std::vector 的保留空间会导致分段错误吗?
- 未命名的命名空间和 iostream 会导致"!= being illegal operation"
- 为什么在我的项目中删除使用命名空间std会导致错误
- 命名空间会导致模板重载解析欠佳
- 在标头中使用未命名的名称空间将如何导致odr违规
- 命名空间的使用导致多个定义
- 匿名名称空间在此处导致未定义的引用-在那里有效