operator=必须是类内非静态成员函数,需按四步深拷贝逻辑实现:自赋值检查→释放旧资源→分配新资源→拷贝数据→返回*this;还须同时提供noexcept移动赋值及正确const参数。

必须手动重载,否则默认行为在含指针/资源时必然崩溃
operator= 必须是类内成员函数
编译器强制要求 operator= 只能作为成员函数重载,不能写成全局函数或友元。这是因为左操作数必须是当前对象,而只有成员函数能天然访问 this。试图写成 MyClass& operator=(const MyClass&, const MyClass&) 会直接编译失败,报错类似 error: 'operator=' must be a non-static member function。
常见误写:
– 把 operator= 声明为 friend(语法错误)
– 在类外定义但没加作用域限定(MyClass& MyClass::operator= 缺了 MyClass::)
– 返回类型写成 void 或 MyClass(破坏链式赋值)
四步不可省略的深拷贝逻辑
安全实现必须严格按顺序执行:释放旧资源 → 分配新资源 → 拷贝数据 → 返回引用。任何跳步都可能引发 double free、内存泄漏或悬空指针。
- 自赋值检查必须放在第一步:
if (this == &other) return *this;,否则delete[] data_会把自己干掉 - 分配新资源前,必须先
delete[] data_(或等价清理),否则旧内存永久泄漏 - 拷贝过程若抛异常(如
new失败),要确保对象处于有效状态——推荐用 copy-and-swap 惯用法规避此风险 - 返回
*this,且类型必须是MyClass&,否则a = b = c中的b = c返回临时量,无法继续赋给a
移动赋值和拷贝赋值要分开实现
只写拷贝赋值 operator=(const MyClass&) 不够。C++11 后,如果类管理动态资源,必须同时提供移动赋值 operator=(MyClass&&),否则右值会被降级为拷贝,性能白丢。
立即学习“C++免费学习笔记(深入)”;
移动赋值的关键动作不是“拷贝”,而是“窃取”:
- 仍需自赋值检查(
this != &other) - 先
delete[] data_清理当前资源 - 直接交换指针:
data_ = other.data_; other.data_ = nullptr; - 务必加
noexcept,否则std::vector扩容时不敢用移动
漏掉移动赋值,或者把移动赋值写成带 new 的深拷贝,等于关掉了现代 C++ 的性能开关。
const 正确性与参数传递方式
参数必须是 const MyClass&,不是 MyClass(避免无谓拷贝)、也不是 MyClass&&(那是移动赋值的签名)。返回类型必须是 MyClass&,且函数本身不加 const(它要修改当前对象)。
容易踩的坑:
- 把参数写成
MyClass other:触发一次不必要的拷贝构造,开销大且可能死循环(如果拷贝构造又调用了operator=) - 返回
const MyClass&:阻止链式赋值,(a = b) = c编译不过 - 在函数体内对
other做非 const 操作(比如调用其非常量成员函数):违反 const 约束,编译失败
真正难的不是写出来,而是每次新增一个裸指针成员,都要同步更新所有五个特殊成员函数(析构、拷贝构造、拷贝赋值、移动构造、移动赋值)——少改一个,运行时就埋一颗雷。


















