c++ - 工作 C++03 代码上的 G++ (C++14) 链接器错误

标签 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;
}

使用 C++03 进行编译并产生输出:

-3
-3
-3

但是,使用 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

奇怪的是,这只发生在 vector b上。如果存在对 double(a) 的强制转换,甚至强制转换为 double 并返回 int (c),则代码将按预期运行。

如何解释这种行为?

最佳答案

直到 C++11,std::vector::resize() 的签名为

void resize( size_type count, T value = T() );

现在是这样了

void resize( size_type count, T const& value );

从按值传递到按常量引用传递的更改导致调用点变为 ODR-use aClass::HALLO 以前没有。转换为 double 然后返回 int 会产生一个临时值,从而避免 ODR 使用;对 a.resize() 的调用也出于同样的原因,因为 int 值隐式转换为 double 并且参数引用是绑定(bind)到生成的临时值。

这里通常的修复是 provide a definition对于aClass::HALLO;如果由于某种原因您不希望这样做,则生成临时值以避免 ODR 使用的简写是应用一元 operator+:

b.resize(10, +aClass::HALLO);

关于c++ - 工作 C++03 代码上的 G++ (C++14) 链接器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50513011/

相关文章:

C++ 错误 : not a member OR multiple definition

c++ - 了解语言环境类,locale::facet::_S_create_c_locale 名称无效

用于以通用方式返回序列的 C++ API

c++ - 编译器评估常量表达式

java - 静态方法可以访问非静态实例变量吗?

gcc - g++ 编译和链接选项

c++ - 编写死亡测试以验证 std::set_terminate 行为

java - 为什么静态字段没有序列化

c++ - 为什么这个 C++ 字符数组似乎能够容纳超过它的大小?

c++ - 我可以从调试二进制文件重建 C++ 源代码吗?