您的位置:首页 > 编程语言 > C语言/C++

C++ String 写时拷贝

2016-03-24 20:27 387 查看
当类里面有指针对象时,采用简单的赋值浅拷贝,使得两个指针指向同一块内存,则析构两次,存在内存奔溃的问题,因此浅拷贝中利用引用计数。
//引用计数浅拷贝
class String
{
public:
String(char*str = "")
:_str(new char[strlen(str) + 1])
, _pRefCount(new int(1))
{}
String(const String & s)
:_str(s._str)
, _pRefCount(s._pRefCount)
{
++(*_pRefCount);
}
String &operator=(const String & s)
{
if (this != &s)
{
if (--(*_pRefCount) == 0)
{
delete[]_str;
delete _pRefCount;
}
_str = s._str;
_pRefCount = s._pRefCount;
++(*_pRefCount);
}
return *this;
}
~String()
{
if (--(*_pRefCount)==0)
{
delete[]_str;
}
}
private:
char*_str;
int*_pRefCount;
};
同之前的delete[ ] 一样,当我们为string 分配内存时,总是多分配一个空间来存储引用计数。在每个内存块的前四个字节来存放一个整数,而真正的内容则在其后。

//写时拷贝
class String
{
public:
String(const char*str="")
:_str(new char[strlen(str)+5])
{
cout << "String()" << endl;
_str += 4;
_GetRefCount(_str) = 1;
strcpy(_str, str);
}

String(const String &s)
:_str(s._str)
{
cout << "String(const String &s)" << endl;
++_GetRefCount(_str);
}

String&operator=(const String &s)
{
if (_str!=s._str)
{
_Release();
_str = s._str;
++_GetRefCount(_str);
}
return *this;
}

~String()
{
cout << "~String()" << endl;
_Release();
}

//写时才拷贝,当两个对象共享一块内存时,若其中的一个需要修改内容,则此时谁修改,谁在另外地方申请新的空间,将之前共用内存块的引用计数减一,将内容复制到新的空间,并把引用计数设置为1.
char&operator[](size_t Index)
{
if (_GetRefCount(_str) > 1)
{
--(_GetRefCount(_str));
char*tmp = new char[strlen(_str) + 5];
tmp += 4;
_GetRefCount(tmp) = 1;
strcpy(tmp, _str);
_str = tmp;
}
return _str[Index];
}

char* C_Str()
{
return _str;
}
private:

int& _GetRefCount(char *str)
{
return *(int*)(str - 4);
}

void _Release()
{
if (--_GetRefCount(_str) == 0)
{
delete[](_str - 4);
}
}

private:
char*_str;
};

void Test2()
{
String s1("xello");
String s2(s1);
s1[0] = 'h';
cout << s1.C_Str() << endl;
cout << s2.C_Str() << endl;
}

int main()
{
Test2();
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息