关于string中的浅拷贝问题

模拟实现string时,要是没有显示定义拷贝构造函数,在拷贝构造一个新的对象时,编译器会调用默认的构造函数默认的拷贝构造函数是怎么样的呢

String(const char* pStr = " ")
	:_pStr(new char[strlen(pStr)+1]) {
		strcpy(_pStr,pStr);
}

调用这个默认的构造函数会出现一个问题,那就是若是拷贝构造1个对象,比如

String s1("hello world");
 String s2(s1);

使用s1拷贝构造s2,注意,现在
s1,s2指向的是同一片内存空间
在销毁对象调用析构函数时

~String() {
		if( _pStr ) {
			delete[] _pStr;
		}
	}

先销毁s2,s2指向的空间释放,s2释放成功,但是s1与s2指向的是同一片内存空间,空间被释放,s1变为野指针,导致程序崩溃

那么如何解决呢
如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情
况都是按照深拷贝方式提供。
主要思路就是给每个对象都分配空间
加深拷贝

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

注意,_str(new char[strlen(s._str)+1]),这里是利用被拷贝函数的指针来开辟新的空间给拷贝的函数,这样子,两个对象就是不同的空间了,释放的时候就不会出现浅拷贝的问题

当然,对于赋值运算符重载也可以使用相同的方法

String& operator=(const String& s) {
		if (this != &s) {
			delete _str;
			_str = new char[strlen(s._str) + 1];
			strcpy(_str, s._str);
		}
		return *this;
	}

还有个现代版的写法

String(const String& s)
		: _str(nullptr)
	{
		String strTemp(s._str);
		swap(_str, strTemp._str);
	}

这里开辟一个strTemp临时空间,使用被拷贝对象的空间(包括数据)开辟临时空间,然后交换拷贝对象与临时空间的空间和数据,这样也可以避免使用相同空间,析构的时候就不会出现浅拷贝现象了

还有一个解决方法,就是写时拷贝技术
这在浅拷贝的基础上加了计数器,构造了对象,资源加一,析构资源减一个,如果计数为1,说明该
对象是资源的最后一个使用者,将该资源释放;否则就不能释放,因为还有其他对象在使用该资源。

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

	String( String& s)
		:_str(s._str)
		
	{
		_count++;
	}

	String& operator=(String s) {
		
		return *this;
	}

	~String() {
		if (_str && 0 == --_count) {
			delete[]_str;
		}
	}

private:
	char* _str;
	static int _count;
};

int String::_count = 0;

void TestString() {
	String s1("hello");
	String s2(s1);

}

int main() {

	return 0;
}

代码扒的,就是这样

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值