考虑下面的代码。
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/