引用计数的浅拷贝的两种实现方式
方法一: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