c++ 拷贝赋值(Copy Assignment)、移动赋值(Move Assignment)

在C++中,拷贝赋值(Copy Assignment)移动赋值(Move Assignment) 是类的重要成员函数,用于控制对象通过赋值操作符 = 时的行为。


一、拷贝赋值函数(Copy Assignment Operator)

用途
将一个已存在的对象(左值)的值复制到另一个已存在的对象中,执行深拷贝(deep copy)。

定义规则

  1. 函数签名为 ClassName& operator=(const ClassName& other)
  2. 必须处理自赋值(如 a = a),避免资源重复释放。
  3. 返回当前对象的引用(*this),支持链式赋值。
  4. 不能使用初始化列表(因为对象已初始化)。

示例

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 引入)。

定义规则

  1. 函数签名为 ClassName& operator=(ClassName&& other)
  2. 参数为右值引用(&&),直接转移资源所有权。
  3. 必须将原对象的资源置为无效状态(如 nullptr),防止重复释放。
  4. 返回当前对象的引用(*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;
    }
};

三、注意事项

  1. 自赋值处理
    必须检查 this != &other,否则可能导致资源提前释放(如拷贝赋值中先 delete[] data,再复制 other.data)。

  2. 返回值
    返回 *this 以支持链式操作,如 a = b = c

  3. 编译器自动生成

    • 若未显式定义拷贝赋值,编译器会生成默认版本(按成员拷贝)。
    • 若未显式定义移动赋值且类无自定义拷贝/析构函数,编译器可能生成默认移动赋值(按成员移动)。
  4. 何时需要自定义

    • 类管理动态资源(如堆内存)时,必须自定义拷贝赋值和移动赋值。
    • 若类不可拷贝(如 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
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值