考虑以下 header 并假设它在多个 TU 中使用:
static int x = 0;
struct A {
A() {
++x;
printf("%d\n", x);
}
};
作为 this question解释说,这是违反 ODR 的,因此是 UB。
现在,there is no ODR violation如果我们的 inline
函数引用了一个非 volatile
const
对象并且我们不在该函数中使用它(加上其他规定) ,所以这在标题中仍然可以正常工作:
constexpr int x = 1;
struct A {
A() {
printf("%d\n", x);
}
};
但如果我们碰巧使用它,我们又回到了与 UB 的第一方:
constexpr int x = 1;
struct A {
A() {
printf("%p\n", &x);
}
};
因此,鉴于我们现在有 inline
变量,不应该将所有 namespace
范围的变量标记为 inline
在标题中避免所有问题?
constexpr inline int x = 1;
struct A {
A() {
printf("%p\n", &x);
}
};
这似乎也更容易教,因为我们可以简单地说“inline
-headers 中的所有内容”(即函数和变量定义),以及“从不 static
在标题中”。
这个推理正确吗?如果是,总是将 header 中的 const
和 constexpr
变量标记为 inline
有什么缺点吗?
最佳答案
正如您所指出的,示例一和示例三确实违反了 [basic.def.odr]/12.2.1 中的 ODR。
[..] in each definition of D, corresponding names, looked up according to [basic.lookup], shall refer to an entity defined within the definition of D, or shall refer to the same entity, after overload resolution and after matching of partial template specialization, except that a name can refer to
a non-volatile const object with internal or no linkage if the object
- is not odr-used in any definition of D, [..]
这个推理正确吗?
是的,具有外部链接的内联变量保证引用相同的实体,即使它们被odr-used,只要所有定义都相同:
An inline function or variable shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case ([basic.def.odr]). [..] An inline function or variable with external linkage shall have the same address in all translation units.
最后一个例子是可以的,因为它满足并且不违反上面的粗体部分。
总是将 header 中的 const 和 constexpr 变量标记为内联有什么缺点吗?
我想不出来,因为如果我们 promise 通过 TU 对具有外部链接的内联变量进行完全相同的定义,编译器可以自由选择其中的任何一个来引用该变量,这将从技术上讲,与只有一个 TU 并在 header 中声明一个带有适当 header 保护的全局变量相同
关于c++ - header 中的 `const` 和 `constexpr` 变量是否应为 `inline` 以防止违反 ODR?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53794625/