大家都知道,重复的开辟空间和释放内存是很耗时的,效率也很低下,相对于写时拷贝,深拷贝就很耗费时间了,效率自然没有写时拷贝好。
写时拷贝是用一个计数器记住当前空间被多少个指针所指向,每次调用析构函数的时候,只需要看看自减后引用计数是否为零(是否只被最后一个指针所指向)。如果是,则销毁空间,如果不是,那么只需要引用计数减减即可,无需释放空间。
写时拷贝是一种高性能的写法,不过这种写法如果不注意就会把引用计数弄错,导致错误。所以在写时拷贝的写法的时候,一定要小心改写引用计数。
下面是重载operator=时的图解
下面是重载operator[]时的图解
下面是代码实现
“test.cpp”
<strong><span style="font-size:18px;">#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
#include "CountCpy.h"
void test1()
{
String s1("hello");
String s2(s1);
String s3(s1);
String s4("world");
s2 = s4;
s4[3] = 'd';
}
int main()
{
test1();
system("pause");
return 0;
}</span></strong>"CountCpy.h"
<strong><span style="font-size:18px;">#define _CRT_SECURE_NO_WARNINGS 1
class String
{
public:
//构造函数
String(const char* str)
:_str(new char[strlen(str)+1+4])
{
_str += 4;//使_str指向数据空间
_GetCount() = 1;
strcpy(_str,str);
}
//析构函数
~String()
{
//如果空间被一块空间所指(即引用计数为1)时
//这个时候才释放空间
if (--_GetCount() == 0)
{
delete[] (_str-4);
}
}
//拷贝构造
String(const String& s)
:_str(s._str)//直接赋值,使这块空间又被指一次
{
//这时候引用计数加加
++_GetCount();
}
String& operator=(String& s)//括号内不能加const,因为会改动到_GetCount()
{
//防止自身给自身赋值
if (this != &s)
{
if (--_GetCount() == 0)
{
delete[] (_str-4);
}
++(s._GetCount());
_str = s._str;
}
return *this;
}
char& operator[](int index)
{
//先屡清楚这块空间是被多少指针所指
if (_GetCount() != 1)
{
--_GetCount();
char* tmp = new char[strlen(_str)+1+4];
strcpy(tmp+4,_str);
_str = tmp+4;
++_GetCount();
}
return _str[index];
}
private:
int& _GetCount()
{
return *((int *)_str-1);
}
private:
char* _str;
};</span></strong>
本文深入探讨了写时拷贝技术的工作原理及其在C++字符串类中的具体应用。通过详细的代码示例,展示了如何利用引用计数来高效管理内存,避免不必要的内存分配与释放,从而提高程序性能。

3676

被折叠的 条评论
为什么被折叠?



