代码之家  ›  专栏  ›  技术社区  ›  Acorn

标头中的'const'和'constexpr'变量是否应该是'inline',以防止ODR冲突?

  •  10
  • Acorn  · 技术社区  · 6 年前

    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);
        }
    };
    

    但如果我们碰巧使用了odr,我们就回到了UB的起点:

    constexpr int x = 1;
    
    struct A {
        A() {
            printf("%p\n", &x);
        }
    };
    

    因此,鉴于我们现在 变量,指南不应该是标记所有变量吗 namespace 内联 在标题中避免所有问题?

    constexpr inline int x = 1;
    
    struct A {
        A() {
            printf("%p\n", &x);
        }
    };
    

    这似乎也更容易教,因为我们可以简单地说“ 内联 -标题中的所有内容(即函数和变量定义)以及“从不” static 在标题中”。

    常数 constexpr 内联

    1 回复  |  直到 4 年前
        1
  •  12
  •   Community CDub    5 年前

    正如您所指出的,示例1和示例3确实违反了ODR [basic.def.odr]/12.2.1

    在每个D定义中,根据[basic.lookup]查找的相应名称应指在D定义中定义的实体, ,在重载解析和匹配部分模板专门化之后,但名称可以引用

    一个非易失性常量对象,如果对象

    • odr不用于D的任何定义中, [..]

    是的,具有外部链接的内联变量保证引用相同的实体,即使它们是 使用的odr

    [dcl.inline]/6

    [..]

    总是将头文件中的const和constexpr变量标记为inline有任何缺点吗?

    我想不出有什么,因为如果我们信守承诺,通过TU的外部链接拥有完全相同的内联变量定义,编译器可以自由选择其中任何一个来引用变量,这在技术上是相同的,因为只有一个TU,并且在头中声明了一个全局变量,并具有适当的头保护