码迷,mamicode.com
首页 > 其他好文 > 详细

写时拷贝(方案三)

时间:2016-03-26 08:31:24      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:string   写时拷贝   copy on write   

以下是其它方案链接地址:

方案一:

http://iynu17.blog.51cto.com/10734157/1755179

方案二:

http://iynu17.blog.51cto.com/10734157/1755185

方案四:(推荐)

http://iynu17.blog.51cto.com/10734157/1755213


方案三

class String
{
    private:
               char* _str;
               size_t  _size;
               size_t  _capacity;
               int* _refCount;       //***
};


方案三设置了一个int型的指针变量用来引用计数,每份内存空间对应一个引用计数,而不是每个对象对应一个引用计数,而且每块内存的引用计数互不影响,不会出现方案一和方案二出现的问题。

技术分享



1.在实现赋值运算符重载要谨慎,不要遇到下图的情形

技术分享


2.改变字符串的某个字符时要谨慎,不要遇到类似下图所遇到的问题。

如果多个对象都指向同一块内存,那么只要一个对象改变了这块内存的内容,那所有的对象都被改变了!!

技术分享

可以用下图的形式改善这种问题:新设置一块内存来存要改变的对象

技术分享

案例3我画的图较多,方便大家结合代码去理解 

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;
#include<assert.h>

class String
{
public:
	String(char* str = "")    //不能strlen(NULL)
	{
		_refCount = new int(1);     //给_refCount开辟空间,并赋初值1
		_size = strlen(str);
		_capacity = _size + 1;
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}
	String(const String &s)
	{
		_refCount = s._refCount;
		_str = s._str;
		_size = strlen(s._str);
		_capacity = _size + 1;
		(*_refCount)++;      //拷贝一次_refCount都要加1
		
	}
	
	//要考虑是s1=s2时,s1原先不为空的情况,要先释放原内存
	//如果要释放原内存时,要考虑它的_refCount减1后是否为0,为零再释放,否则其它对象指针无法再访问这片空间
	String& operator=(String& s)  
	{
		if (_str!= s._str)
		{
			_size = strlen(s._str);
			_capacity = _size + 1;
			if (--(*_refCount) == 0)
			{
				delete[] _str;
				delete _refCount;
			}
			
			_str = s._str;
			_refCount = s._refCount;
			(*_refCount)++;
		}		
		return *this;
	}
	//如果修改了字符串的内容,那所有指向这块内存的对象指针的内容间接被改变
	//如果还有其它指针指向这块内存,我们可以从堆上重新开辟一块内存空间,
	//把原字符串拷贝过来
	//再去改变它的内容,就不会产生链式反应
	//  1.减引用计数  2.拷贝   3.创建新的引用计数
	char& String::operator[](const size_t index) //参考深拷贝      
	{
		if (*_refCount==1)
		{
			return *(_str + index);
		}
		else
		{
			--(*_refCount);
			char* tmp = new char[strlen(_str)+1];
			strcpy(tmp, _str);
			_str = tmp;
			_refCount = new int(1);
			return *(_str+index);
		}
	}
	~String()
	{
		if (--(*_refCount)== 0)  //当_refCount=0的时候就释放内存
		{
			delete[] _str;
			delete _refCount;
			_str = NULL;
			cout << "~String " << endl;
		}
		_size = 0;
		_capacity = 0;
	}
	friend ostream& operator<<(ostream& output, const String &s);
	friend istream& operator>>(istream& input, const String &s);
private:
    char* _str;      //指向字符串的指针
    size_t  _size;      //字符串大小
    size_t  _capacity;   //容量
    int* _refCount;    //计数指针
};


ostream& operator<<(ostream& output, const String &s)
{
	output << s._str;
	return output;
}
istream& operator>>(istream& input, const String &s)
{
	input >> s._str;
	return input;
}

void Test()    //用例测试
{
	String s1("abcdefg");
	String s2(s1);
	String s3;
	s3 = s2;
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	s2[3] = ‘0‘;
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;

	//String s4("opqrst");
	//String s5(s4);
	//String s6 (s5);
	//s6 = s4;
	//cout << s4 << endl;
	//cout << s5 << endl;
	//cout << s6 << endl;

}
int main()
{
	Test();
	system("pause");
	return 0;
}

本文出自 “言安阳” 博客,谢绝转载!

写时拷贝(方案三)

标签:string   写时拷贝   copy on write   

原文地址:http://iynu17.blog.51cto.com/10734157/1755208

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!