引用计数的浅拷贝的两种实现方式
方法一:String类中采用char* _str和int* _pRefCount;但利用指针_pRefCount重新开辟空间存放引用计数,会产生大量内存碎片。
代码如下:
#include<iostream>
using namespace std;
#include<assert.h>
class String
{
public:
String(char* str="")
:_str(new char[strlen(str)+1])
,_pRefCount(new int[1])
{
strcpy(_str, str);
*_pRefCount = 1;
}
String(const String& s)
:_str(s._str)
,_pRefCount(s._pRefCount)
{
++(*_pRefCount);
}
//运算符重载
String& operator=(const String& s)
{
if (--(*_pRefCount) == 0)
{
delete[] _str;
delete _pRefCount;
}
_str = s._str;
_pRefCount = s._pRefCount;
++(*_pRefCount);
return *this;
}
~String()
{
if (--(*_pRefCount) == 0)
{
cout << "~String()" << endl;
delete[] _str;
delete _pRefCount;
}
}
int _GetRefCount()
{
return *_pRefCount;
}
void put()
{
cout << _str << endl;
}
private:
char* _str;
int* _pRefCount;
};
void Test()
{
String S;
String s1("Luoluo");
String s2(s1);
S.put();
s2 = s1;
s2.put();
//监视查看或断言判断是否正确
assert(s1._GetRefCount() == 2);
assert(s2._GetRefCount() == 2);
String s3("Feifei");
String s4(s3);
s3.put();
s3 = s1;
s3.put();
assert(s1._GetRefCount() == 3);
assert(s2._GetRefCount() == 3);
assert(s3._GetRefCount() == 3);
assert(s4._GetRefCount() == 1);
}
int main()
{
Test();
system("pause");
return 0;
}
方法二:类中只采用_str一个变量,用开辟的前一块空间存放引用计数。利用强制转换前后偏移,获取引用计数以及存放字符串的位置。对于两个或多个相同的字符串,为了方便修改某字符串,并不影响其他字符串可以通过写实拷贝来实现。
代码如下:
#include<iostream>using namespace std;class String{public:String(char* str = ""):_str(new char[strlen(str)+5]){_str += 4;_GetRefCount(_str) = 1;strcpy(_str, str);}String(const String& s):_str(s._str){++_GetRefCount(_str);}String& operator=(const String& s){if (_str != s._str){_Release();_str = s._str;++_GetRefCount(_str);}return *this;}//写实拷贝-----写谁谁拷贝char& operator[](size_t index){if (_GetRefCount(_str) > 1){char* tmp = new char[strlen(_str) + 5];tmp += 4;_GetRefCount(tmp) = 1;strcpy(tmp, _str);--_GetRefCount(_str);_str = tmp;}return _str[index];}~String(){cout << "~String()" << endl;_Release();}int& _GetRefCount(char* str){return(*(int*)(str - 4));}void _Release(){if (--(_GetRefCount(_str)) == 0){delete[](_str - 4);//指针返回首地址位置,释放整段空间}}void put(){cout << _GetRefCount(_str)<<"---------"<<_str << endl;}private:char* _str;};void Test(){String S;String s1 = "abclefg";String s2(s1);S.put();s1.put();s2.put();s2 = s1;s2.put();String s3 = "hijklmn";String s4(s3);s3.put();s3 = s1;s3.put();s1[3] = 'd';s1.put();s2.put();}int main(){Test();system("pause");return 0;}
本文出自 “Scen” 博客,请务必保留此出处http://10741357.blog.51cto.com/10731357/1747871