C++深浅拷贝

浅拷贝的缺点:

对类内的成员变量按字节,一个一个的简单拷贝,这就是浅拷贝,对于日期类对象,没有在堆上创建数据的对象,浅拷贝是可行的,但是对于栈对象,需要在在堆上创建数据的对象,我们需要用到深拷贝来完成对象的拷贝,为了实现深拷贝,我们需要自己实现拷贝构造函数

以下面这段代码为例,证明以上发生的错误

    class string
	{
	public:
		string(const char* s = "\0")//默认构造初始化
			: _size(strlen(s))
			,_capacity(_size)
		{
			_str = new char[_capacity + 1];//这里的+1是为了存放'\0'
		}
		~string()
		{
			delete[] _str;//析构释放
		}
	private:
		char* _str;
		int _size;
		int _capacity;
	};

	void Test()
	{
		string s1;
		string s2 = s1;
	}

上面这段代码没有写深拷贝构造函数以及深拷贝复制重载函数,当对象s1赋值给s2的时候,发生了堆地址浅拷贝,然后程序结束的时候,重复释放了同一个堆上的空间,造成报错。

利用深拷贝解决问题:

为了解决上面的错误,我们提出了深拷贝构造函数和深拷贝复制重载函数,代码模板如下所示:

	class string
	{
	public:
		string(const char* s = "\0")
			: _size(strlen(s))
			,_capacity(_size)
		{
			_str = new char[_capacity + 1];
			strcpy(_str, s);
		}
		~string()
		{
			delete[] _str;
		}
		string(const string& s)
			:_size(s._size)
			, _capacity(s._capacity)
		{
			_str = new char[_capacity + 1];
			strcpy(_str, s._str);
		}
		string& operator=(string& s)
		{
			//if (this != &s)
			//{
			//	//delete[] _str;
			//	不管申请空间失败与否,都会把对象的_str给释放掉
			//	为了避免这种情况发生,就采用了临时变量的赋值方式
			//	//_str = new char[s._capacity + 1];
			//	//strcpy(_str, s._str);
			//	//_capacity = s._capacity;
			//	//_size = s._size;
			//}
			//return *this;
			if (this != &s)
			{
				char* tmp = new char[s._capacity + 1];
				strcpy(tmp, s._str);
				delete[] _str;
				_str = tmp;
				_capacity = s._capacity;
				_size = s._size;
			}
			return *this;
		}
	private:
		char* _str;
		int _size;
		int _capacity;
	};

	void Test()
	{
		string s1;
		string s2 = s1;
	}

最后生成的s1对象中的_str和s2对象中的_str指向的空间是不一样的,但是它们空间里的内容是一样的。

深拷贝的现代写法:

在深拷贝的传统写法中,需要申请栈上的空间,然后调用strcpy函数将需拷贝的对象的数据拷贝到当前对象刚申请的栈上,那我们细想一下,如果通过调用拷贝构造函数产生一个新的临时对象,然后将该临时对象的成员变量与当前对象的成员变量进行交换,不就可以省去调用strcpy函数,使代码效率提高了嘛?

  

		//深拷贝的传统写法
		string(const string& s)
			:_str(nullptr)
			,_size(s._size)
			,_capacity(s._capacity)
		{
			_str = new char[_capacity + 1];
			strcpy(_str, s._str);
		}

		//深拷贝的现代写法
		string(const string& s)
			:_str(nullptr)
			,_size(0)
			,_capacity(0)
		{
			string ttmp(s._str);
			Swap(ttmp);
		}

		//赋值重载函数深拷贝
		string& operator=(string s)//传参调用拷贝构造
		{
			Swap(s);
			return *this;
		}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值