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

C++类深拷贝赋值运算符实现问题及VS调试无法步入求助

C++深拷贝未生效且赋值运算符未被调用的问题排查与修复

核心问题:指针赋值未触发对象赋值运算符

你的测试代码中copyTrophy = newTrophy;是指针变量的赋值,只是让copyTrophy指针指向了newTrophy指针所指向的同一个Trophy对象内存地址,完全没有调用你重载的operator=。这就是为什么修改原对象后拷贝对象跟着变,以及调试进不去赋值运算符的原因——这个方法根本没被执行过。

正确的对象赋值方式

把指针赋值改成对象的赋值操作,直接操作指针指向的对象:

// 替换原来的 copyTrophy = newTrophy;
*copyTrophy = *newTrophy;

或者更简洁的方式,直接使用拷贝构造函数创建拷贝对象,避免多余的默认构造调用:

// 不需要先new默认构造的对象,直接用拷贝构造
Trophy* copyTrophy = new Trophy(*newTrophy);

赋值运算符的缺陷修复

你当前的operator=存在两个严重问题:

  1. 未释放当前对象已有的动态内存:直接给name、level、color赋新的new出来的指针,原来的指针指向的内存会丢失,造成内存泄漏。
  2. 未处理自赋值情况:如果出现obj == this的自赋值,会先释放内存再拷贝,导致非法访问。

修复后的赋值运算符:

Trophy& Trophy::operator=(const Trophy& obj){
    // 先处理自赋值
    if (this == &obj) {
        return *this;
    }

    // 释放当前对象已有的动态内存
    delete name;
    delete level;
    delete color;

    // 深拷贝新的内存
    name = new string(*obj.name);
    level = new int(*obj.level);
    color = new Color(*obj.color);

    return *this;
}

必须补充的析构函数

你的类成员都是动态分配的内存,但没有提供析构函数来释放这些内存,会导致程序运行时持续泄漏内存。添加析构函数:

Trophy::~Trophy() {
    delete name;
    delete level;
    delete color;
}

补充拷贝构造函数(可选但推荐)

为了完整遵循三法则(如果重载了赋值运算符、析构函数,就需要拷贝构造函数),建议实现拷贝构造函数,确保通过拷贝构造创建对象时也能完成深拷贝:

Trophy::Trophy(const Trophy& obj) {
    // 深拷贝成员
    name = new string(*obj.name);
    level = new int(*obj.level);
    color = new Color(*obj.color);
}

测试代码修改后的完整示例

修改后的主函数:

#include <iostream>
#include <string>
using namespace std;

enum Color { BRONZE, SILVER, GOLD };

class Trophy {
private:
    string* name = new string;
    int* level = new int;
    Color* color = new Color;
public:
    Trophy();
    Trophy(const Trophy& obj);
    ~Trophy();
    Trophy& operator=(const Trophy& obj);

    void setName(const string& n) { *name = n; }
    void setLevel(int l) { *level = l; }
    void setColor(Color c) { *color = c; }

    string getName() const { return *name; }
    int getLevel() const { return *level; }
    Color getColor() const { return *color; }
};

// 构造函数
Trophy::Trophy() {
    *name = "";
    *level = 0;
    *color = BRONZE;
}

// 拷贝构造函数
Trophy::Trophy(const Trophy& obj) {
    name = new string(*obj.name);
    level = new int(*obj.level);
    color = new Color(*obj.color);
}

// 析构函数
Trophy::~Trophy() {
    delete name;
    delete level;
    delete color;
}

// 修复后的赋值运算符
Trophy& Trophy::operator=(const Trophy& obj){
    if (this == &obj) {
        return *this;
    }

    delete name;
    delete level;
    delete color;

    name = new string(*obj.name);
    level = new int(*obj.level);
    color = new Color(*obj.color);

    return *this;
}

int main() {
    Trophy* newTrophy = new Trophy();
    newTrophy->setName("My Trophy");
    newTrophy->setLevel(10);
    newTrophy->setColor(GOLD);

    cout << newTrophy->getName() << " " << newTrophy->getLevel() << " " << newTrophy->getColor() << endl;

    // 使用拷贝构造创建拷贝对象
    Trophy* copyTrophy = new Trophy(*newTrophy);
    // 或者使用赋值运算符:
    // Trophy* copyTrophy = new Trophy();
    // *copyTrophy = *newTrophy;

    cout << copyTrophy->getName() << " " << copyTrophy->getLevel() << " " << copyTrophy->getColor() << endl;

    newTrophy->setName("Please work");
    newTrophy->setLevel(5);
    newTrophy->setColor(SILVER);

    cout << newTrophy->getName() << " " << newTrophy->getLevel() << " " << newTrophy->getColor() << endl;
    cout << copyTrophy->getName() << " " << copyTrophy->getLevel() << " " << copyTrophy->getColor() << endl;

    // 记得释放动态分配的对象,避免内存泄漏
    delete newTrophy;
    delete copyTrophy;

    return 0;
}

运行这个修改后的代码,修改原对象后,拷贝对象的内容不会跟着改变,且赋值运算符会被正常调用,调试时可以步入该方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 15:15:30