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

C++中使用拷贝构造函数实现深拷贝的问题求助

问题根源

你写的拷贝构造逻辑是对的,但**N2 = N1调用的是默认赋值运算符,它做的是浅拷贝**——直接把N1的指针a、b的地址复制给N2,导致两个对象的指针指向同一块堆内存,修改N1的内容自然会影响N2。

拷贝构造函数只在新建对象并初始化时生效(比如Number N2(N1);或Number N2 = N1;),而你代码里的N2已经通过默认构造函数创建完成,此时用=触发的是赋值运算符,不是拷贝构造。

解决方法:重载赋值运算符

给Number类加上重载的赋值运算符,实现深拷贝逻辑,同时处理自赋值和内存泄漏问题:

#include <iostream>
using namespace std;

class Number
{
private:
    int* a;
    int* b;

public:
    // 默认构造函数
    Number() {
        a = new int;
        b = new int;
        *a = 0;
        *b = 0;
    }
    
    // 带参构造函数
    Number(int val1, int val2) {
        a = new int;
        b = new int;
        *a = val1; 
        *b = val2;
    }
    // 拷贝构造函数(你原来的实现没问题)
    Number(const Number& other) {
        a = new int;
        b = new int;
        *a = *(other.a);
        *b = *(other.b);
    }

    // 重载赋值运算符(核心新增部分)
    Number& operator=(const Number& other) {
        // 处理自赋值:避免自己赋值给自己时的内存错误
        if (this == &other) {
            return *this;
        }

        // 先释放当前对象已有的堆内存,防止泄漏
        delete a;
        delete b;

        // 重新分配内存并复制值,实现深拷贝
        a = new int;
        b = new int;
        *a = *(other.a);
        *b = *(other.b);

        return *this; // 返回自身,支持链式赋值(比如N3 = N2 = N1)
    }

    // 析构函数!必须添加,否则会导致堆内存泄漏
    ~Number() {
        delete a;
        delete b;
    }

    // getters and setters
    int getA() {
        return *a;
    }
    int getB() {
        return *b;
    }
    void setA(int val) {
        *a = val;
    }
    void setB(int val) {
        *b = val;
    }

    void print() {
        cout << "value of a: " << *a << " value of b: " << *b << endl;
    }
};

int main()
{
    Number N1(2,3), N2;

    N1.print(); // 输出:value of a: 2 value of b: 3
    N2.print(); // 输出:value of a: 0 value of b: 0

    N2 = N1;
    
    N1.print(); // 输出:value of a: 2 value of b: 3
    N2.print(); // 输出:value of a: 2 value of b: 3

    N1.setA(12);

    N1.print(); // 输出:value of a: 12 value of b: 3
    N2.print(); // 输出:value of a: 2 value of b: 3 (现在N2和N1完全独立)
}
额外提醒
  1. 必须加析构函数:你原来的代码没有析构函数,对象销毁时不会释放a、b指向的堆内存,会造成内存泄漏。
  2. 自赋值检查不能少:如果跳过这一步,当执行N1 = N1时,会先释放自己的内存,再去访问已释放的内存,触发未定义行为。
  3. 若使用C++11及以上版本,还可以实现移动构造和移动赋值来优化性能,但当前先解决深拷贝的核心需求即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 01:50:28