具有3个构造函数的结构TB,下面的代码编译和复制构造函数 - "构造函数A"被叫两次。评论"构造函数C"导致编译问题。
这是什么原因?
为什么在构造函数B中取消注释const会影响编译结果?
这是否与覆盖默认的复制赋值运算符有关?
这里适用的解决规则是什么?
int doIgetHere = 0;
struct TA{
int a;
};
struct TB{
int b;
//Constructor A
TB(TA &ta){
b = ta.a;
}
//Constructor B
TB(/*const*/ TB &tb){
doIgetHere++;
b = tb.b;
}
// Constructor C === removing this constructor cause compilation problem, why ?
TB(TB && mtb){
doIgetHere++;
b = mtb.b;
}
};
int main(){
TA ta;
TB tb1(ta); // using constructor A
TB tb2 = ta; // using constructor A
std::cout<<doIgetHere<<"\n"; // result is 0, as expected
}
编译日志:
34:5:错误:没有可行的构造函数复制类型&#39; TB&#39;
TB tb2 = ta; // using constructor A ^ ~~
18:2:注意:候选构造函数不可行:期望第一个参数的l值
TB(/*const*/ TB &tb){ ^ 1 error generated.
答案 0 :(得分:2)
当你这样做时
TB tb2 = ta;
实际上等于
TB tb2 = TB(ta);
换句话说,临时对象是从ta
创建的,然后在 copy-constructor (您的构造函数B)中使用。
这里的问题是非const引用不能绑定到临时对象。解决方案只是使参数成为一个常量引用(由于某种原因你注释掉了)。
使用非标准的移动构造函数(构造函数C),可以将临时对象作为参数,这是rvalue引用如何工作的部分。