c++ - 由于标头中的匿名命名空间导致 ODR 违规
问题描述
通过阅读标准,我无法确定以下代码是否违反 ODR:
// a.h
#ifndef A_HEADER_FILE
#define A_HEADER_FILE
namespace {
int v;
}
inline int get_v() { return v; }
#endif // A_HEADER_FILE
// a.cpp
#include "a.h"
void f() {
int i = get_v();
// ...
}
// b.cpp
#include "a.h"
void g() {
int i = get_v();
// ...
}
(来源:https ://wiki.sei.cmu.edu/confluence/display/cplusplus/DCL59-CPP.+Do+not+define+an+unnamed+namespace+in+a+header+file )
据说,get_v()
在每个翻译单元中引用了不同的变量,所以它违反了ODR
.
这个答案:内联函数和外部链接说内联放松ODR
了所以我不确定为什么这仍然是一个错误?
ODR
如果这是违规行为,有人可以将我链接到标准中指定的位置吗?
解决方案
一个inline
函数允许有多个定义(C++17 [basic.def.odr]/6)。这就是inline
可以使用函数来防止 ODR 违规的意义。但是,inline
函数的多个定义必须相互一致。具体来说,[basic.def.odr]/6.2 说:
在 的每个定义中
D
,根据 6.4 查找的相应名称应指在 的定义中定义的实体D
,或应指同一实体 [...] [一些例外]
的多个定义get_v
引用变量v
,但v
未定义在内部get_v
。因此,要求每个定义get_v
引用相同的变量v
。情况并非如此,因为每个翻译单元都有不同的v
. 因此,违反了 ODR。
推荐阅读
- php - 在 Laravel 的同一页面上发布评论和显示评论
- python - Flask-sqlalchemy 临时会话/上下文变量
- django - 如何在 django 中同时在两个不同的数据库表中插入值?
- javascript - 如何在角度7中的一个ngfor下将两个不同插值中的值相乘
- clips - Is there a way to logically bind values from two different multislots?
- python - opencv/cv2/opencv-python 名称不匹配,如何说服 pip 不查找已通过 conda 安装的包?
- java - 如何在 javafx 中使用节点方法 setAll() 和 addAll()?
- sql - 如何从包含逗号分隔条目的变量中创建(不同的)值列表?
- laravel - 如何转换雄辩的关系对象?
- python - 错误=surrogateescape vs 错误=替换