Linux操作下String类的实现--引用计数器
1.引用计数器写法一
写法一个人比较喜欢叫他双指针法,因为他是在类里面创建了两个指针来实现的一个是指针_str,另外一个是用来保存指向同一块空间个数的指针_pRefCount.
class String
{
public:
String(char* str = "")
:_str(new char[strlen(str) + 1])
, _pRefCount(new int(1))
{
strcpy(_str, str);
}
String(String& s)
:_str(s._str)
, _pRefCount(s._pRefCount)
{
++(*_pRefCount);
}
String& operator=(const String& s)
{
/*char* tmp = new char[strlen(s._str) + 1];
strcpy(tmp, s._str);
delete[] _str;
_str = tmp;*/ //这种写法不符合引用计数器的原理
/*swap(_str, s._str);*/
if (--(*_pRefCount) == 0)
{
delete[] _str;
delete[] _pRefCount;
}
_str = s._str;
_pRefCount = s._pRefCount;
++(*_pRefCount);
return *this;
}
~String()
{
if (--(*_pRefCount) == 0)
{
delete[] _str;
delete[] _pRefCount;
}
}
private:
char* _str;
/*static int _refCount;*///变成静态的以后,需要在类的外面定义
int* _pRefCount;
};
//int String::_refCount = 0;
void Test1()
{
String s1("xxx");
String s2(s1);
String s3("yyy");
s3 = s2;
/*String s4(s3);*/
}
int main()
{
Test1();
system("pause");
return 0;
}
这种写法简单易懂,也容易想到,但是由于要开辟两块空间一块大的一块小的,容易造成系统产生很多的内存碎片,所以有了另外一种写法
2.引用计数器写法二
这种写法的思路是在开辟空间时多开辟四个字节的空间,在头部用四个字节的空间来保存指向同一块空间的个数,这样即避免了内存碎片的产生,也使得操作起来更为方便,不要要操作两块空间。
class String{public: String(char* str = "") :_str(new char[strlen(str) + 5]) { *(int*)_str = 1; _str += 4; strcpy(_str, str); } String(String& s) :_str(s._str) { ++(*(int*)(_str - 4)); } String& operator=(const String& s) { if (_str != s._str) { Release(); _str = s._str; ++GetRefCount(_str); } return *this; } ~String() { if (--(*(int*)(_str - 4)) == 0) { delete[](_str - 4); } } int& GetRefCount(char* str) { return *(int*)(str - 4); } void Release() { if (--GetRefCount(_str) == 0) { delete[](_str - 4); } }private: char* _str;};int main(){ system("pause"); return 0;}