You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++深拷贝机制中operator=实现:为何拷贝构造可用但赋值运算符失效?

问题解答

核心差异

拷贝构造函数和拷贝赋值运算符的运行场景本质不同,是你遇到问题的核心原因:

  • 拷贝构造函数在创建全新对象时触发,此时对象的m_name指针还没有指向任何堆内存,你直接为其分配新内存存储拷贝内容即可,无需处理旧有资源
  • 拷贝赋值运算符作用于已经完成初始化的已有对象,此时m_name已经指向了之前分配的堆内存,你没有先处理原有内存就直接赋值,自然会出现各类问题

错误写法分析

你注释掉的尝试写法都有明确的问题:

  • m_name = p.m_name:纯浅拷贝,两个对象的m_name指针指向同一块堆内存,两个对象析构时会先后释放同一块内存,触发double free崩溃
  • 直接执行m_name = new std::string(*p.m_name):没有释放当前对象原有m_name指向的旧内存就直接覆盖指针,造成内存泄漏
  • 尝试分配std::string数组的写法完全错误:你需要的是单个std::string对象,分配数组的操作和后续析构用delete(而非delete[])的逻辑不匹配,直接触发未定义行为
  • 数组循环拷贝逻辑错误:把单个std::string指针当成数组处理,属于越界访问,运行结果完全不可预期

正确实现

最简单的正确写法如下:

Person& operator=(const Person& p) {
    if (&p == this) return *this;
    // 先释放原有内存
    delete m_name;
    // 深拷贝新内容
    m_name = new std::string(*p.m_name);
    return *this;
}

如果需要更高的异常安全性(避免new失败时不会破坏当前对象的原有内容),可以使用copy-and-swap写法:

class Person {
    // 类内新增swap友元
    friend void swap(Person& a, Person& b) noexcept {
        std::swap(a.m_name, b.m_name);
    }
public:
    // 原有其他函数保持不变
    Person& operator=(Person p) { // 传值参数自动完成拷贝构造
        swap(*this, p);
        return *this;
    }
};

内容的提问来源于stack exchange,提问作者Sam Smith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 12:57:03