我遇到了一个测验,说下面第18行中的代码格式不正确,因为“当需要复制的其中一个成员是一个引用时,使用隐式定义的赋值运算符是不正确的。” / p>
我无法理解。为什么参考无法复制?为什么16号线合法?第16行与第18行非常相似,复制构造函数仍然需要复制,对吧?
1 #include <iostream>
2
3 struct A
4 {
5 A(int& var) : r(var) {}
6
7 int &r;
8 };
9
10 int main(int argc, char** argv)
11 {
12 int x = 23;
13
14 A a1(x);
15
16 A a2 = a1;
17
18 a2 = a1;
19
20 return 0;
21 }
答案 0 :(得分:6)
第16行使用复制构造函数,第18行使用赋值运算符operator=
。两种不同的功能有不同的限制。
因为引用无法反弹,所以编译器无法生成任何有意义的隐式赋值运算符。因此它拒绝这样做,并产生错误。
复制构造函数第一次生成对象,因此它可以像在您自己的构造函数中一样绑定该引用。
答案 1 :(得分:3)
具有引用成员的类没有默认提供的复制/移动赋值运算符。一旦建立绑定,引用就不能反弹以引用不同的变量。简而言之,复制构造函数正在进行初始化,而默认赋值运算符将尝试在绑定后更改。
因此,该标准将此情况称为默认复制和移动赋值运算符。
C ++11§12.8p23
如果X具有:
,则将类X的默认复制/移动赋值运算符定义为已删除
你当然可以写你自己的重载。
#include <iostream>
struct A
{
A(int& var) : r(var) {}
int &r;
A& operator=(const A& obj)
{
r = obj.r; // value copied, reference-binding remains the same
return *this;
}
};
int main(int argc, char** argv)
{
int x = 42;
int y = 43;
A a1(x);
A a2(y);
A a3 = a1; // legal. default copy-ctor invoked
a3 = a2; // legal. user-defined copy-assignment invoked
std::cout << x << ',' << y << '\n';
return 0;
}
<强>输出强>
43,43
但是这不会(也不能)重新引用引用。此处提供的重载会更改引用的数据;不是参考本身。这种区别很重要。
希望这有帮助。
答案 2 :(得分:1)
因为C++
重新分配参考资料是违法的。
int &a = some_int;
a = some_other_int; // value copied not reference
a = some_int; // value copied not reference
当您使用赋值运算符(由编译器生成)时,它会盲目地执行对象的复制,从而尝试重新分配您的引用,因此无效。
当你说a2 = a1;
时,编译器会尝试将a1.r
重新分配给a2.r
,使其在编译时失败,因为它是错误的。
您可以将引用视为automatically dereferenced constant pointer
。因此,行a2 = a1;
将保持格式不正确的原因与下面的类相同。
struct A
{
A(int *var) : p(var) {}
int * const p;
};