c++ - 运算符重载 = 修改原始对象
问题描述
struct List {
int size;
int* items;
List& operator=(const List& l);
};
List& List::operator=(const List& l)
{
delete[] items;
size = l.size;
items = new int[20];
for (int i = 0; i < size; i++)
items[i] = l.items[i];
return *this;
}
ostream& operator<<(ostream& out, const List& l)
{
out << "Size: " << l.size << "\t {";
for (int i = 0; i < l.size; i++)
out << l.items[i] << " ";
return (out << "}");
}
int main()
{
int size = 6;
List l1 = { size, new int[size]{ 0, 1, 2, 3, 4, 5 } };
List l2 = l1;
l2.items[1] = 50;
cout << l1 << endl;
cout << l2 << endl;
return 0;
}
我很困惑,因为当我使用重载运算符分配l2 = l1时,为什么 l1 的内容会在稍后更改 l2 时发生变化?特别是因为 l1 作为 const 传递。它们以某种方式指向内存中的同一个对象,而不是副本。
解决方案
List l2 = l1;
不调用复制赋值运算符 ( operator=(const List& l)
)。由于“赋值”发生在变量声明期间,您改为l2
通过复制初始化进行初始化,该初始化调用编译器生成的默认复制构造函数。由于它进行了浅拷贝,因此两个对象都将指向相同的数据。
如果您要编写自己的管理内存/资源的类,您至少需要提供自己的复制构造函数、复制赋值运算符和析构函数。这被称为三法则。如果要包含移动语义,则需要提供移动构造函数和移动赋值运算符,这被称为 5 规则。还有零规则,使用已经“做正确的事情”的类型(就像使用 a ) 允许编译器生成的默认值为您工作,您可以在三/五/零规则中std::vector
阅读所有内容
推荐阅读
- javascript - quill-image-resize-vue 中的对齐错误
- api - 如何通过phab api将来自gitlab的repo导入Phabricator?
- microsoft-graph-api - 使用 ms graph API 更改团队活动的会议选项
- c - libdrm 是否通过 ioctl() 与内核 DRM/显卡通信?
- java - GroovyShell:将标准错误重定向到 StringWriter
- html - 从网站上抓取网站图标
- google-apps-script - 如何在谷歌文档中获取行尾字符的位置
- terraform - Terraform Range 函数从 1 而不是 0 开始
- swift - 如何快速知道这个 NSObject 是类还是协议?
- node.js - 跟踪 Node.js 程序执行