为什么 如果类的成员是引用,则复制对象是非法的
Why It is illegal to copy an object if a member of the class is a reference?
我遇到了一个测验,说下面第 18 行的代码格式不正确,因为"当需要复制的成员之一是引用时,使用隐式定义的赋值运算符是格式不正确的。
我无法理解。为什么无法复制参考文献?为什么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 }
16 行使用复制构造函数,第 18 行使用赋值运算符operator=
。两种不同的功能,具有不同的限制。
由于引用无法重新绑定,因此编译器无法生成有意义的隐式赋值运算符。因此,它拒绝这样做,并生成错误。
复制构造函数是第一次生成对象,因此它可以像在自己的构造函数中一样绑定该引用。
引用成员的类没有默认提供的复制/移动赋值运算符。建立绑定后,无法重新绑定引用以引用其他变量。简而言之,复制构造函数正在进行初始建立,而默认赋值运算符将尝试在绑定后更改它。
因此,该标准对默认复制和移动分配运算符都调用了这种情况。
C++11 § 12.8p23
如果 X 具有以下条件,则类 X 的默认复制/移动赋值运算符定义为已删除:
- 具有非平凡的相应赋值运算符的变体成员,并且 X 是类似联合的类,或者
- const 非类类型(或其数组)的非静态数据成员,或
- 引用类型的非静态数据成员,或 类类型为 M(
- 或其数组)的非静态数据成员,由于应用于 M 的相应赋值运算符的重载解析 (13.3) 导致歧义或函数从默认赋值运算符中删除或无法访问,因此无法复制/移动,或者
- 无法复制/移动的直接或虚拟基类 B,因为应用于 B 的相应赋值运算符的重载解析 (13.3) 会导致歧义或函数从默认赋值运算符中删除或无法访问,或者 对于移动赋值运算符,
- 类型不具有移动赋值运算符且不可轻易复制的非静态数据成员或直接基类,或任何直接或间接的虚拟基类。
您当然可以编写自己的重载。
#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
但这不会(也不能)重新绑定引用。此处提供的重载会更改引用的数据;不是参考文献本身。这种区别很重要。
希望这有帮助。
分配给引用在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;
};
- 将包含不可复制对象的对插入到映射中
- 通用参考 l 值不复制对象
- 为什么具有 2 个参数参数的构造函数接受复制对象作为 1 个参数参数?
- 为什么从引用创建共享指针会复制对象?
- 当(且仅当)对象具有复制构造函数时,如何复制对象?
- 我的程序运行良好,可以复制对象,但是当我使用复制分配(=)时,它仍然可以正常运行.为什么不给错误
- 如何复制对象
- 如何构造不可移动不可复制对象的元组?
- 不可复制对象数组的 consexpr 初始化?
- 提升::可选与标准::不可复制对象的可选
- 如何在C++中通过引用复制对象
- 从指针复制对象
- 删除浅表的复制对象和源对象
- 使用realloc可以安全地重新分配琐碎的可复制对象的存储吗
- C 返回复制对象
- 如何将智能指针作为类属性来复制对象
- 为什么在复制对象时忽略顶级常量
- std::shared_ptr 在复制对象时导致问题
- 安全复制对象的替代方案
- 当类包含boost::container::flat_set时,复制对象时出错