关于工作C++ 03代码的G ++(C++ 14)链接器错误

Ric*_*rdo 2 c++ static g++ linker-errors

考虑以下代码.

class aClass
{
public:
    static const int HALLO = -3;
};

int main()
{
  std::vector<double > a;
  std::vector<int> b;
  std::vector<int> c;
  int d = aClass::HALLO; //fine
  a.resize(10,aClass::HALLO); //fine
  b.resize(10,aClass::HALLO); // linker error c++11 and c++14
  c.resize(10,(int)(double)aClass::HALLO); //fine
  std::cout<<a[0]<<endl;
  std::cout<<b[0]<<endl;
  std::cout<<c[0]<<endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译与C++ 03一起使用并产生输出:

-3
-3
-3
Run Code Online (Sandbox Code Playgroud)

但是,使用C++ 11或C++ 14进行编译会导致链接器错误:

/tmp/cc3BARzY.o: In Funktion `main':
main.cpp:(.text+0x66): Nicht definierter Verweis auf `aClass::HALLO'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

奇怪的是,这只发生在矢量上b.如果有一个强制转换为double(a)或甚至是double并返回到int(c),则代码按预期运行.

如何解释这种行为?

ild*_*arn 7

Pre-C++ 11的签名std::vector::resize()

void resize( size_type count, T value = T() );
Run Code Online (Sandbox Code Playgroud)

现在它反过来了

void resize( size_type count, const value_type& value );
Run Code Online (Sandbox Code Playgroud)

从pass-by-value到pass-by-const-ref的更改导致callsite 在以前没有使用的 aClass::HALLO地方使用ODR.double然后再投射回来以int避免使用ODR的方式产生临时性; 由于a.resize()同样的原因调用了作品,因为该int值被隐式地强制转换为double绑定参数之前的参数.

这里通常的解决办法是提供一个定义aClass::HALLO; 如果出于某种原因对你不利,那么产生临时性以避免ODR使用的简写就是应用一元operator+:

b.resize(10, +aClass::HALLO);
Run Code Online (Sandbox Code Playgroud)