C++深拷贝和浅拷贝

浅拷贝,当类对象调用编译器默认的拷贝构造函数和赋值运算符重载函数的时候,仅将待复制对象各个数据成员的值对应复制过来。
深拷贝,通过程序员的重写编写拷贝构造函数和赋值运算符重载函数,让对象中动态成员,重新动态分配空间。【即指针重新指向另一个堆】

举例:

浅拷贝的危害【当有指针的时候就体现出来了】:

using namespace std;
class A {
public:
    A(int a)
    {
        cout << "类型转换构造函数" << endl;
        b = new int[a];
    }public:
    int a;
    int* b;
};

int main() 
{
    A a(10);
    A b(a);//使用的是默认的拷贝构造函数
    cout << "a:" << (a.b) << "  b:" << (b.b);
    getchar();
    return 0;
}

结果:

发现a和b中的指针对象都指向同一片堆,所以当a和b某个先被析构的时候,另一个的指针对象就指向了空堆,空指针也就来了。

解决:如果有指针对象就自己定义拷贝构造函数和赋值运算符函数

ps:深拷贝不应该是种和浅拷贝对应的概念,而应该是为了解决浅拷贝的弊端而出现的一种解决思路。

 

 

 

实际操作中因为浅拷贝产生的问题:

 

 如上图有一个读取配置文件的类,有个指针属性指向QSetting,然后通过构造函数传递,默认是浅拷贝,如下:

 

运行到函数第一行后,this的cfg和入参cfg的QSetting指针指向同一个堆,然后入参在函数结束后释放了这个堆,this的QSetting就找不到这个堆了,以至于我的程序一直卡在了使用QSetting的地方。

 

ps:

1、其他理解:对于A = B【https://www.lanindex.com/stdmove%E5%AE%9E%E9%99%85%E5%BA%94%E7%94%A8%E5%88%86%E6%9E%90/】

深拷贝:A先申请出一片新的空间,完全复制B的内容到新空间中;

浅拷贝:A复制B指针,将自己的指针指向B的内容地址,A、B公用一块内存地址;

 

2、一个不错的例子【https://blog.csdn.net/zhoumoon/article/details/108276324】

//MemoryBlock.cpp
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class MemoryBlock
{
public:
   explicit MemoryBlock(size_t length):_length(length),_data(new int[length])
   {
        cout << "In MemoryBlock(size_t). length = "
                << _length << "." << endl;
   }
~MemoryBlock() { cout << "In ~MemoryBlock(). length = " << _length << "."; if(_data!=nullptr) { cout << " Deleting resource."; delete[] _data; } cout<<endl; } MemoryBlock(const MemoryBlock& other):_length(other._length), _data(new int[other._length]) { cout << "In MemoryBlock(const MemoryBlock&). length = " << other._length << ". Copying resource." << endl; copy(other._data,other._data+other._length,this->_data); } MemoryBlock& operator = (const MemoryBlock& other) { cout << "In operator=(const MemoryBlock&). length = " << other._length << ". Copying resource." << std::endl; if(this!=&other) { delete[] this->_data; this->_length = other._length; this->_data = new int[this->_length]; copy(other._data,other._data + this->_length,this->_data); } return *this; } size_t Length() const { return _length; } private: size_t _length; int* _data; }; int main(int argv,char* argc[]) { // Create a vector object and add a few elements to it. vector<MemoryBlock> v; v.push_back(MemoryBlock(25)); v.push_back(MemoryBlock(75)); // Insert a new element into the second position of the vector. v.insert(v.begin() + 1, MemoryBlock(50)); return 0; }

打印:

In MemoryBlock(size_t). length = 25.
In MemoryBlock(const MemoryBlock&). length = 25. Copying resource.
In ~MemoryBlock(). length = 25. Deleting resource.
In MemoryBlock(size_t). length = 75.
In MemoryBlock(const MemoryBlock&). length = 75. Copying resource.
In MemoryBlock(const MemoryBlock&). length = 25. Copying resource.
In ~MemoryBlock(). length = 25. Deleting resource.
In ~MemoryBlock(). length = 75. Deleting resource.
In MemoryBlock(size_t). length = 50.
In MemoryBlock(const MemoryBlock&). length = 50. Copying resource.
In MemoryBlock(const MemoryBlock&). length = 25. Copying resource.
In MemoryBlock(const MemoryBlock&). length = 75. Copying resource.
In ~MemoryBlock(). length = 75. Deleting resource.
In ~MemoryBlock(). length = 25. Deleting resource.
In ~MemoryBlock(). length = 50. Deleting resource.
In ~MemoryBlock(). length = 75. Deleting resource.
In ~MemoryBlock(). length = 50. Deleting resource.
In ~MemoryBlock(). length = 25. Deleting resource.

 

posted @ 2019-09-19 14:35  朱小勇  阅读(538)  评论(0编辑  收藏  举报