【C++】一篇文章彻底搞懂浅拷贝和深拷贝

前言

先抛出两者的概念:
浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共 享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以当继续对资源进项操作时,就会发生发生了访问违规。要解决浅拷贝问题,C++中引入了深拷贝。
深拷贝:如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供。

简单的来说,浅拷贝是增加了一个指针,指向原来已经存在的内存。而深拷贝是增加了一个指针,并新开辟了一块空间,让指针指向这块新开辟的空间。

浅拷贝

看一段代码:

class String
{
    
    
public:
	String(const char* str = "")
	{
    
    
		if (nullptr == str)
		{
    
    
			_str = new char[1];
			*_str = '0';
		}
		else
		{
    
    
			_str = new char[strlen(str) + 1];
			strcpy(_str, str);
		}
	}

	//编译器生成的默认拷贝构造函数---浅拷贝
	String(const String& s)
		: _str(s._str)
	{
    
     }

	//编译器生成的默认赋值运算符重载---浅拷贝
	String& operator=(const String& s)
	{
    
    
		_str = s._str;
		return *this;
	}
	~String()
	{
    
    
		if (_str)
		{
    
    
			delete[] _str;
			_str = nullptr;
		}
	}
	friend ostream&operator<<(ostream & _cout, const String &s)
	{
    
    
		_cout << s._str;
		return _cout;
	}
private:
	char* _str;
};

int main()
{
    
    
	String s1("hello");
	String s2(s1);
	String s3("world");
	s3 = s1;
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	return 0;
}

结果:
在这里插入图片描述
查看监视窗口,我们发现s1、s2、s3在同一块空间:
在这里插入图片描述
我们写的析构函数:

~String()
{
    
    
	if (_str)
	{
    
    
		delete[] _str;
		_str = nullptr;
	}
}

s3先析构,析构完后空间释放掉,因为s1、s2、s3在同一块空间,所以这个时候已经没s1、s2啥事了~~~,所以出现了崩溃。

深拷贝

在上边的代码的基础上,修改了拷贝构造函数和赋值运算符函数

class String
{
    
    
public:
	String(const char* str = "")
	{
    
    
		if (nullptr == str)
			str = "";
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}

	String(const String& s)
		: _str(new char[strlen(s._str)+1])
	{
    
    
		strcpy(_str, s._str);
	}

	String& operator=(const String& s)
	{
    
    
		if (this != &s)
		{
    
    
			char* temp = new char[strlen(s._str) + 1];
			strcpy(temp, s._str);
			delete[] _str;
			_str = temp;
		}
		return *this;
	}
	~String()
	{
    
    
		if (_str)
		{
    
    
			delete[] _str;
			_str = nullptr;
		}
	}
	friend ostream&operator<<(ostream & _cout, const String &s)
	{
    
    
		_cout << s._str;
		return _cout;
	}
private:
	char* _str;
};
int main()
{
    
    
	String s1("hello");
	String s2(s1);
	String s3("world");
	s3 = s1;
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	return 0;
}

结果:
在这里插入图片描述
此时,s1、s2、s3在不同空间
在这里插入图片描述

总结

浅拷贝:只是增加一个指针,指向原来的空间。多个对象在底层共用一份资源,最终在这些对象销毁时,该份资源释放多次,而引起代码崩溃。
深拷贝:新增加指针,并新开辟空间,让每个对象中都拥有自己独立的资源。

猜你喜欢

转载自blog.csdn.net/zhao_leilei/article/details/109451290