📜  C ++中的浅复制和深复制(1)

📅  最后修改于: 2023-12-03 15:29:43.015000             🧑  作者: Mango

C++中的浅复制和深复制

在C++中,当我们定义一个类对象并将其赋值给另一个对象时,会发生复制。然而,不同的复制方式会导致不同的结果。本文将介绍C++中的两种复制方式:浅复制和深复制。

浅复制

浅复制是指只复制对象的值,而不复制指向对象的指针或引用。这意味着如果一个对象的某个成员指向堆上的内存,那么复制这个对象只会复制它的地址,而不会复制指向的内存。

下面是一个例子:

#include<iostream>
using namespace std;

class ShallowCopy {
public:
    ShallowCopy(int size) {
        m_data = new int[size];
        m_size = size;
    }
    ~ShallowCopy() {
        delete[] m_data;
    }
    void setValue(int index, int value) {
        m_data[index] = value;
    }
    void printData() {
        for(int i = 0; i < m_size; ++i) {
            cout << m_data[i] << " ";
        }
        cout << endl;
    }
private:
    int* m_data;
    int m_size;
};

int main() {
    ShallowCopy source(5);
    source.setValue(0, 1);
    source.setValue(1, 2);
    source.setValue(2, 3);
    source.printData();

    ShallowCopy copy = source; // 浅复制
    copy.setValue(0, 10);
    copy.printData(); // 输出:10 2 3
    source.printData(); // 输出:10 2 3

    return 0;
}

在上面的代码中,我们定义了一个ShallowCopy类,它包含一个指向堆上整型数组的指针。在main函数中,我们先定义了一个source对象,然后对它进行了一些操作(修改了前三个元素的值),并打印了它的所有元素。接着,我们定义了一个copy对象,将source对象赋值给它。这时,copy对象和source对象的m_data指向同一个堆对象,即它们共享同一片内存。我们在copy对象中修改了第一个元素的值为10,然后分别打印了copy对象和source对象的所有元素。可以看到,两个对象的第一个元素都被修改了。

这里的关键问题是,由于浅复制只复制了指针m_data的地址,而没有复制它所指向的堆内存,所以当我们修改copy对象中的m_data时,source对象的m_data也会被修改。

深复制

深复制是指在复制对象时,不仅要复制对象的值,还要复制对象指向的所有内存。深复制会为新对象分配一块新的内存,然后将指针或引用指向这个新的内存。这样,新对象和原对象就不再共享一片内存。

下面是一个例子:

#include<iostream>
using namespace std;

class DeepCopy {
public:
    DeepCopy(int size) {
        m_data = new int[size];
        m_size = size;
    }
    ~DeepCopy() {
        delete[] m_data;
    }
    DeepCopy(const DeepCopy& other) { // 深复制构造函数
        m_size = other.m_size;
        m_data = new int[m_size];
        for(int i = 0; i < m_size; ++i) {
            m_data[i] = other.m_data[i];
        }
        cout << "DeepCopy constructor is called." << endl;
    }
    void setValue(int index, int value) {
        m_data[index] = value;
    }
    void printData() {
        for(int i = 0; i < m_size; ++i) {
            cout << m_data[i] << " ";
        }
        cout << endl;
    }
private:
    int* m_data;
    int m_size;
};

int main() {
    DeepCopy source(5);
    source.setValue(0, 1);
    source.setValue(1, 2);
    source.setValue(2, 3);
    source.printData();

    DeepCopy copy = source; // 深复制
    copy.setValue(0, 10);
    copy.printData(); // 输出:10 2 3
    source.printData(); // 输出:1 2 3

    return 0;
}

在上面的代码中,我们定义了一个DeepCopy类,并额外定义了一个深复制构造函数。在main函数中,我们定义了一个source对象,并对它进行了一些操作(同样是修改前三个元素的值)。接着,我们定义了一个copy对象,并将source对象赋值给它。这时,copy对象和source对象都拥有了自己的内存空间,它们互不干扰。我们在copy对象中修改了第一个元素的值为10,然后分别打印了copy对象和source对象的所有元素。可以看到,copy对象的第一个元素被修改了,而source对象的元素没有变化。

这里的关键问题是,由于深复制为copy对象分配了一块新的内存空间,并将source对象的数据全部复制到它的内存空间中,所以当我们修改copy对象中的数据时,它不会影响到source对象。

总结

C++中的复制方式有两种:浅复制和深复制。浅复制只复制对象的值,而不复制指向对象的指针或引用;这造成了对象之间的共享内存。而深复制则会为新对象分配一块独立的内存空间,然后将原对象的数据全部复制到其中,从而使它们互不干扰。在实际应用中,我们需要根据情况来选择不同的复制方式,以保证程序的正确性和可靠性。