c++深拷贝与浅拷贝

来源:互联网 发布:qq晒米软件 编辑:程序博客网 时间:2024/05/17 06:34

类的聚集:

类的成员中含有某个类的指针,就叫做类的聚集。对象中只存放数据的地址,数据可以是数组或者对象等。

浅拷贝:

对象之间的元素一一复制,这就是拷贝构造函数的本能。当数据成员是指针时,就会出现问题!

深拷贝:

被复制的对象数据成员是指针类型时,不会复制指针成员本身,而是将指针所指向的对象进行复制!

浅拷贝demo

#include <iostream>using namespace std;class Basic {public:    Basic() {        cout << "default Basic() run" << endl;    }    Basic(int x, int y) {        this->x = x;        this->y = y;        cout << "Basic(int x, int y) run" << endl;    }    ~Basic() {        cout << "de-constructor ~Basic() run" << endl;    }    int GetX() { return this->x; }    int GetY() { return this->y; }    void Assign(int x, int y) {        this->x = x;         this->y = y;    }private:    int x, y;};class low_copy_Basic : public Basic {public:    low_copy_Basic(int length) {        this->numberOfBasic = length;         this->pointer = new Basic[length];    }    ~low_copy_Basic() {        cout << "~low_copy_Basic() run..." << endl;        this->numberOfBasic = 0;        delete[] this->pointer;    }    Basic &GetElement(int length) {        return this->pointer[length];    }private:    Basic *pointer;    int numberOfBasic;};int main(void){    // Assign    low_copy_Basic obj_1 = low_copy_Basic(2);    obj_1.GetElement(0).Assign(1, 2);    obj_1.GetElement(1).Assign(3, 4);    low_copy_Basic obj_2 = low_copy_Basic(obj_1);    cout << "obj_2" << endl;    cout << obj_2.GetElement(0).GetX() << " and " << obj_2.GetElement(0).GetY() << endl;    cout << obj_2.GetElement(1).GetX() << " and " << obj_2.GetElement(1).GetY() << endl;    // change    obj_2.GetElement(0).Assign(5, 6);    obj_2.GetElement(1).Assign(7, 8);    cout << "after change, obj_1 :" << endl;    cout << obj_1.GetElement(0).GetX() << " and " << obj_1.GetElement(0).GetY() << endl;    cout << obj_1.GetElement(1).GetY() << " and " << obj_1.GetElement(1).GetY() << endl;    return EXIT_SUCCESS;}

Basic类有x y 两个数据成员,其派生类low_copy_Basic有Basic * 和长度计数。
注意,派生类我使用的是默认的拷贝构造函数,因此它执行浅拷贝,仅仅拷贝成员对应的元素本身,这也是运行后出现错误的根源!因为派生类对象obj_1和obj_2指向了同一个内存区域pointer!析构函数delete了两次!

运行结果:
low_copy

深拷贝demo

#include <iostream>using namespace std;class Basic {public:    Basic() {        cout << "default Basic() run" << endl;    }    Basic(const int x, const int y) {        this->x = x;        this->y = y;        cout << "Basic(int x, int y) run" << endl;    }    ~Basic() {        cout << "de-constructor ~Basic() run" << endl;    }    int GetX() { return this->x; }    int GetY() { return this->y; }    void Assign(const int x, const int y) {        this->x = x;         this->y = y;    }private:    int x, y;};class low_copy_Basic : public Basic {public:    low_copy_Basic() {        this->numberOfBasic = 0;         this->pointer = nullptr;    }    low_copy_Basic(int length) {        this->numberOfBasic = length;         this->pointer = new Basic[length];    }    ~low_copy_Basic() {        cout << "~low_copy_Basic() run..." << endl;        this->numberOfBasic = 0;        delete[] this->pointer;    }    low_copy_Basic(const low_copy_Basic &rhs);    Basic &GetElement(int length) {        return this->pointer[length];    }private:    Basic *pointer;    int numberOfBasic;};low_copy_Basic::low_copy_Basic(const low_copy_Basic &rhs) {    int current_length = rhs.numberOfBasic;    this->pointer = new Basic[current_length];    for (int i = 0; i < current_length; ++i)        this->pointer[i].Assign(rhs.pointer[i].GetX(), rhs.pointer[i].GetY());}int main(void){    // Assign    low_copy_Basic obj_1 = low_copy_Basic(2);    obj_1.GetElement(0).Assign(1, 2);    obj_1.GetElement(1).Assign(3, 4);    low_copy_Basic obj_2 = low_copy_Basic(obj_1);    cout << "obj_2" << endl;    cout << obj_2.GetElement(0).GetX() << " and " << obj_2.GetElement(0).GetY() << endl;    cout << obj_2.GetElement(1).GetX() << " and " << obj_2.GetElement(1).GetY() << endl;    // change    obj_2.GetElement(0).Assign(5, 6);    obj_2.GetElement(1).Assign(7, 8);    cout << "after change, obj_1 :" << endl;    cout << obj_2.GetElement(0).GetX() << " and " << obj_1.GetElement(0).GetY() << endl;    cout << obj_2.GetElement(1).GetX() << " and " << obj_1.GetElement(1).GetY() << endl;    return EXIT_SUCCESS;}

不再使用默认的拷贝构造函数,因为派生类成员含有指针,因此逐个拷贝所指向的数据,从而正确完成拷贝,称之为“深拷贝“

执行结果如下:
deep_copy2

0 0