当类里面有指针对象时,采用简单的赋值浅拷贝,使得两个指针指向同一块内存,则析构两次,存在内存奔溃的问题,因此浅拷贝中利用引用计数。
//引用计数浅拷贝
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;
}本文出自 “printf的返回值” 博客,请务必保留此出处http://10741125.blog.51cto.com/10731125/1754944
原文地址:http://10741125.blog.51cto.com/10731125/1754944