自学内容网 自学内容网

【c++语言程序设计】深层复制与浅层复制(深拷贝与浅拷贝)

浅层复制

浅层复制是指复制构造函数仅仅将对象的成员逐一复制,而不管成员类型是否是指针。如果一个类拥有指针成员并且采用浅层复制,那么复制对象时只会复制指针的地址,而不会复制指针所指向的数据。换句话说,多个对象共享同一块内存。

默认的复制构造函数,是对数据项的直接复制 (浅层复制)——编写复制构造函数的必要性

深层复制

为了避免浅层复制的问题,我们可以自定义复制构造函数,手动创建一份对象数据的“深层副本”。深层复制会为新对象分配新的内存空间,并将数据逐项复制,确保每个对象的数据独立

 


浅层复制——代码(存在问题的版本) 

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

class Point {
private:
    int x, y;  // 坐标

public:
    Point(int x = 0, int y = 0) : x(x), y(y) {}

    int getX() const { return x; }
    int getY() const { return y; }

    void move(int newX, int newY) 
    {  // 移动到新坐标
        x = newX;
        y = newY;
    }
};

class ArrayOfPoints 
{
private:
    Point* points;  // 指向动态数组
    int size;

public:
    ArrayOfPoints(int size) : size(size) 
    {
        points = new Point[size];  // 分配内存
    }

    ~ArrayOfPoints() 
    {
        delete[] points;  // 释放内存
    }

    Point& element(int index) {  // 返回引用,方便修改
        assert(index >= 0 && index < size);
        return points[index];
    }
};

int main() {
    int count;
    cout << "Please enter the count of points: ";
    cin >> count;

    ArrayOfPoints pointsArray1(count);  // 创建对象数组
    pointsArray1.element(0).move(5, 10);
    pointsArray1.element(1).move(15, 20);

    // 浅层复制构造函数自动生成,直接赋值
    ArrayOfPoints pointsArray2 = pointsArray1;

    cout << "Copy of pointsArray1:" << endl;
    cout << "Point 0 of array2: " << pointsArray2.element(0).getX() << ", " << pointsArray2.element(0).getY() << endl;
    cout << "Point 1 of array2: " << pointsArray2.element(1).getX() << ", " << pointsArray2.element(1).getY() << endl;

    // 修改 pointsArray1 的坐标
    pointsArray1.element(0).move(25, 30);
    pointsArray1.element(1).move(35, 40);

    // 输出 pointsArray2 的坐标,观察浅层复制的问题
    cout << "After the moving of pointsArray1:" << endl;
    cout << "Point 0 of array2: " << pointsArray2.element(0).getX() << ", " << pointsArray2.element(0).getY() << endl;
    cout << "Point 1 of array2: " << pointsArray2.element(1).getX() << ", " << pointsArray2.element(1).getY() << endl;

    return 0;
}

问题: pointsArray1pointsArray2 共用了同一块内存,因此移动 pointsArray1 中的点也会影响 pointsArray2 中的点。

默认的复制构造函数将两个对象的对应数据项简单复制后,pointsArrayl 的成员 points 和 pointsArray2 的成员 points具有相同的值,也就是说两个指针指向的是同一内存地址,表面上好像完成了复制,但是并没有形成真正的副本。因此当程序中移动 pointsArrayl 中的点时,也影响到了 pointsArray2。 这种效果就是“浅层复制”。

浅层复制还有更大的弊病,在程序结束之前 pointsArrayl 和pointsArray2 的析构函数会自动被调用,动态分配的内存空间会被释放。由于两个对象共用了同一块内存空间,因此该空间被两次释放,于是导致运行错误

此问题可以通过实现深层复制解决【编写复制构造函数

ArrayOfPoints(const ArrayOfPoints& v) : size(v.size) {
    points = new Point[size];  // 分配独立的动态内存
    for (int i = 0; i < size; i++) {
        points[i] = v.points[i];  // 将每个元素逐个复制到新数组中
    }
}

通过逐元素复制来保证数据一致性,但又不影响两个对象的独立性。 

深层复制是解决对象中指针成员共享内存问题的有效方法。在有指针成员的类中,深层复制构造函数是必不可少的。

深层复制——代码

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

class Point {
private:
    int x, y;  // 坐标

public:
    Point(int x = 0, int y = 0) : x(x), y(y) {}

    int getX() const { return x; }
    int getY() const { return y; }

    void move(int newX, int newY) {  // 移动到新坐标
        x = newX;
        y = newY;
    }
};

class ArrayOfPoints {
private:
    Point* points;  // 指向动态数组
    int size;

public:
    ArrayOfPoints(int size) : size(size) {
        points = new Point[size];  // 分配内存
    }

    // 实现深层复制构造函数
    ArrayOfPoints(const ArrayOfPoints& v) : size(v.size) {
        points = new Point[size];  // 分配新内存
        for (int i = 0; i < size; i++) {
            points[i] = v.points[i];  // 逐一复制数组中的点
        }
    }

    ~ArrayOfPoints() {
        delete[] points;  // 释放内存
    }

    Point& element(int index) {  // 返回引用,方便修改
        assert(index >= 0 && index < size);
        return points[index];
    }
};

int main() {
    int count;
    cout << "Please enter the count of points: ";
    cin >> count;

    ArrayOfPoints pointsArray1(count);  // 创建对象数组
    pointsArray1.element(0).move(5, 10);
    pointsArray1.element(1).move(15, 20);

    // 使用深层复制构造函数创建 pointsArray2
    ArrayOfPoints pointsArray2 = pointsArray1;

    cout << "Copy of pointsArray1:" << endl;
    cout << "Point 0 of array2: " << pointsArray2.element(0).getX() << ", " << pointsArray2.element(0).getY() << endl;
    cout << "Point 1 of array2: " << pointsArray2.element(1).getX() << ", " << pointsArray2.element(1).getY() << endl;

    // 修改 pointsArray1 的坐标
    pointsArray1.element(0).move(25, 30);
    pointsArray1.element(1).move(35, 40);

    // 输出 pointsArray2 的坐标,验证深层复制是否正确
    cout << "After the moving of pointsArray1:" << endl;
    cout << "Point 0 of array2: " << pointsArray2.element(0).getX() << ", " << pointsArray2.element(0).getY() << endl;
    cout << "Point 1 of array2: " << pointsArray2.element(1).getX() << ", " << pointsArray2.element(1).getY() << endl;

    return 0;
}


 总结

  • 浅层复制适用于类成员无指针、无动态内存的简单场景。

  • 深层复制适用于包含动态内存的类,确保每个对象拥有独立的数据副本,避免共享内存和双重释放问题。

    参考教材:C++语言程序设计 (第5版) 郑莉 董渊 编著


原文地址:https://blog.csdn.net/Z15922342915/article/details/143497168

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!