c++ - 在类静态常量 ODR

标签 c++ gcc linker one-definition-rule

我对 static 有点困惑const 的类内初始化成员。例如,在下面的代码中:

#include <iostream>

struct Foo
{
    const static int n = 42;
};

// const int Foo::n; // No ODR

void f(const int& param)
{
    std::cout << param << std::endl;
}

int g(const int& param)
{
    return param;
}

template<int N>
void h()
{
    std::cout << N << std::endl;
}

int main()
{
    // f(Foo::n); // linker error, both g++/clang++
    std::cout << g(Foo::n) << std::endl; // OK in g++ only with -O(1,2 or 3) flag, why?!
    h<Foo::n>(); // this should be fine
}

Live example

我没有定义 Foo::n (该行已注释)。所以,我期待电话 f(Foo::n)在链接时失败,确实如此。但是,以下行 std::cout << g(Foo::n) << std::endl;每当我使用诸如 -O1/2/3 之类的优化标志时,只能通过 gcc 编译和链接(clang 仍然会发出链接器错误) .

  1. 为什么打开优化后 gcc(尝试使用 gcc5.2.0 和 gcc 4.9.3)编译并链接代码?
  2. 我说类内静态常量成员的唯一用法是在常量表达式中,例如 h<Foo::n> 中的模板参数是否正确?调用,在这种情况下代码应该链接?

最佳答案

我假设编译器在优化期间执行以下操作:

  • const static int n 在任何地方都是内联的。没有为变量 n 分配内存,对它的引用变得无效。函数 f() 需要对 n 的引用,因此程序不会被编译。

  • g 函数简短。它被有效地内联和优化。优化后,函数g不需要引用n,它只返回常量值42。

解决方法是在类外定义变量:

struct Foo
{
    const static int n;
};

const int Foo::n = 42;

关于c++ - 在类静态常量 ODR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32812663/

相关文章:

c++ - 解析具有变化字段的消息

c++ - 使用-std = c++ 0x时未声明nullptr

gcc - g++ 'nullptr' 未在此范围内声明

无法使用 clang 编译和链接程序

c++ - 链接器如何在剥离的动态库中定位代码?

c++ - 什么是 NULL 值

c++ - 如何在c/c++中设置与函数同名的定义?

c - 宏扩展中 OpenMP Pragma 的错误替换

c++ - 在C++中链接多个目标文件但没有输出

c++ - 类型为“std::string&”的非常量引用的无效初始化