c++ 拷贝赋值(Copy Assignment)、移动赋值(Move Assignment)
在C++中,拷贝赋值(Copy Assignment) 和 移动赋值(Move Assignment) 是类的重要成员函数,用于控制对象通过赋值操作符 = 时的行为。
一、拷贝赋值函数(Copy Assignment Operator)
用途:
将一个已存在的对象(左值)的值复制到另一个已存在的对象中,执行深拷贝(deep copy)。
定义规则:
- 函数签名为
ClassName& operator=(const ClassName& other)。 - 必须处理自赋值(如
a = a),避免资源重复释放。 - 返回当前对象的引用(
*this),支持链式赋值。 - 不能使用初始化列表(因为对象已初始化)。
示例:
class String {
public:
char* data;
size_t size;
// 拷贝赋值函数
String& operator=(const String& other) {
if (this != &other) { // 处理自赋值
delete[] data; // 释放原有资源
size = other.size;
data = new char[size + 1];
strcpy(data, other.data);
}
return *this; // 返回当前对象引用
}
};
二、移动赋值函数(Move Assignment Operator)
用途:
从临时对象(右值)中“窃取”资源,避免不必要的深拷贝,提高性能(C++11 引入)。
定义规则:
- 函数签名为
ClassName& operator=(ClassName&& other)。 - 参数为右值引用(
&&),直接转移资源所有权。 - 必须将原对象的资源置为无效状态(如
nullptr),防止重复释放。 - 返回当前对象的引用(
*this)。
示例:
class String {
public:
char* data;
size_t size;
// 移动赋值函数
String& operator=(String&& other) {
if (this != &other) { // 处理自赋值(虽然罕见)
delete[] data; // 释放当前资源
data = other.data; // 窃取资源
size = other.size;
other.data = nullptr; // 置空原对象
other.size = 0;
}
return *this;
}
};
三、注意事项
-
自赋值处理:
必须检查this != &other,否则可能导致资源提前释放(如拷贝赋值中先delete[] data,再复制other.data)。 -
返回值:
返回*this以支持链式操作,如a = b = c。 -
编译器自动生成:
- 若未显式定义拷贝赋值,编译器会生成默认版本(按成员拷贝)。
- 若未显式定义移动赋值且类无自定义拷贝/析构函数,编译器可能生成默认移动赋值(按成员移动)。
-
何时需要自定义:
- 类管理动态资源(如堆内存)时,必须自定义拷贝赋值和移动赋值。
- 若类不可拷贝(如
std::unique_ptr),需删除拷贝赋值(operator=(const T&) = delete)。
四、完整示例
#include <cstring>
class String {
public:
char* data;
size_t size;
// 构造函数
String(const char* s = "") {
size = strlen(s);
data = new char[size + 1];
strcpy(data, s);
}
// 析构函数
~String() {
delete[] data;
}
// 拷贝赋值
String& operator=(const String& other) {
if (this != &other) {
delete[] data;
size = other.size;
data = new char[size + 1];
strcpy(data, other.data);
}
return *this;
}
// 移动赋值
String& operator=(String&& other) {
if (this != &other) {
delete[] data;
data = other.data;
size = other.size;
other.data = nullptr;
other.size = 0;
}
return *this;
}
};
int main() {
String a("Hello");
String b;
b = a; // 调用拷贝赋值
String c;
c = std::move(a); // 调用移动赋值(a 的资源被转移)
return 0;
}
五、总结
| 特性 | 拷贝赋值 | 移动赋值 |
|---|---|---|
| 参数类型 | const T&(左值引用) | T&&(右值引用) |
| 资源操作 | 深拷贝 | 资源转移(避免拷贝) |
| 自赋值处理 | 必须检查 | 建议检查 |
| 性能 | 较低(需拷贝数据) | 高(直接转移指针) |
| 适用场景 | 常规赋值操作 | 临时对象或显式转移资源(std::move) |
1万+

被折叠的 条评论
为什么被折叠?



