浅拷贝和深拷贝

mac2025-04-01  17

一、什么是深拷贝和浅拷贝

    简单的来说,【浅拷贝】是增加了一个指针,指向原来已经存在的内存。而【深拷贝】是增加了一个指针,并新开辟了一块空间让指针指向这块新开辟的空间。浅拷贝只是增加了指向同一个空间的对象。而深拷贝则是新建了全新的对象,它具有自己的空间。对于一个空类,编译器默认生成四个成员函数:默认构造函数、析构函数、拷贝构造函数、赋值函数。而直立棉的拷贝构造函数是浅拷贝。所以这时候如果类中含有指针变量,默认的拷贝构造函数必定出错。

二、浅拷贝

    这里给出一个浅拷贝的例子。

#include <iostream> #include <string> using namespace std; class String { public: // 构造函数 String(const char* pStr = "") { if (NULL == pStr) { pstr = new char[1]; *pstr = '\0'; } else { pstr = new char[strlen(pStr) + 1]; // 加1, 某位是'\0',结束符 strcpy(pstr, pStr); } } // 拷贝构造函数 String(const String& s) { pstr = s.pstr; // 浅拷贝的问题,指向同一块空间,可能造成释放的错误 ,这是浅拷贝的缺点 } // 赋值运算符重载 String& operator = (const String& s) { if (this != &s) { delete[] pstr; // 将原来所指向的空间释放 pstr = s.pstr; // 让pstr重新指向s的pstr所指向的空间(也会导致错误) } return *this; } ~String() { // 2. 插入断点 if (NULL != pstr) { delete[] pstr;//释放指针所指向的内容 pstr = NULL;//将指针置为空 } } friend ostream& operator<<(ostream& _cout, const String& s) { _cout << s.pstr; return _cout; } private: char* pstr; }; int main() { // 1. 插入断点 String s1("sss"); String s2(s1); String s3(NULL); s3 = s1; cout << s1 << endl; cout << s2 << endl; cout << s3 << endl; return 0; }

    这里我们将三个对象添加到监视里,发现他们的地址都是一样。     在析构函数处插入断点,析构s3时,将空间释放掉了,可以析构s2的时候报错了。因为它地址所处的空间就是s3的空间,以及被释放掉了,所以报错了。

三、深拷贝

    深拷贝和浅拷贝的不同之处,仅仅在于修改了下【拷贝构造函数】,以及【赋值运算符的重载】。其实是给每个新建的对象分配了空间。

// 拷贝构造函数 String(const String& s) { pstr = new char[strlen(s.pstr) + 1]; strcpy(pstr, s.pstr); } // 赋值运算符重载 String& operator = (const String& s) { if (this != &s) { char* tmp = new char[strlen(s.pstr) + 1];//动态开辟一个临时变量,然后将pstr指向这一个新的临时变量里 delete[] pstr;//将原来的空间进行释放 strcpy(tmp, s.pstr);//将s.pstr里的内容复制到临时变量中 pstr = tmp;//pstr指向临时变量的这段空间 } return *this; }

    现在可以看出三个对象的地址都不一样了,程序运行没有问题了。     这边可以简化一下深拷贝的【拷贝构造函数】,【赋值运算符重载】

// 拷贝构造函数 String(const String& s) { // 调用构造函数 String temp(s.pstr); swap(pstr, temp.pstr); } // 赋值运算符重载 String& operator = (const String& s) { if (this != &s) { // 调用构造函数 String temp(s.pstr); swap(pstr, temp.pstr); } return *this; }

四、总结

浅拷贝只是增加了一个指针,指向已存在对象的内存。浅拷贝在多个对象指向一块空间的时候,释放一个空间会导致其他对象所使用的空间也被释放了,再次释放便会出现错误深拷贝是增加了一个指针,并新开辟了一块空间,让指针指向这块新开辟的空间。
最新回复(0)