欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > C++:string类写时拷贝|引用计数

C++:string类写时拷贝|引用计数

2024/10/25 21:26:55 来源:https://blog.csdn.net/lusanjiu/article/details/142562062  浏览:    关键词:C++:string类写时拷贝|引用计数


Blog’s 主页: 白乐天_ξ( ✿>◡❛)
🌈 个人Motto:他强任他强,清风拂山冈!
💫 欢迎来到我的学习笔记!

写时拷贝(了解)

参考博客:C++写时拷贝的不同方案(String类)_c++ string 从第三个字节拷贝-CSDN博客

1.1 概念

  • 在此之前,我们就有讲过深浅拷贝的问题
    • 浅拷贝会导致同一块空间析构两次;
    • 一个对象进行修改等变化会影响另一个对象(因为同一个地址同一块空间)
  • 因此我们使用深拷贝解决该问题:先开辟空间后拷贝数据。但是这种方法需要我们没创建一个对象就去深拷贝,可在后面该对象并没有做任何修改操作,那么深拷贝的作用就不大了,而且还浪费了内存空间资源。(深拷贝:每次对对象进行值和空间同时拷贝,但是会使用更多的空间
  • 因此就有了写时拷贝。当对空间进行修改时,检查出来自己以外是否还有其他对象使用此空间。有,自己重新开辟空间进行修改,不去影响其他对象;没有,则表示是自己空间资源独享,直接进行更改。而这里引入引用计数,用于统计有多少对象在使用这块空间资源

1.2 方案1

画板

  • 当创建出一个对象s1,利用s1拷贝构造出一个对象s2,引用技术refCount自动+1,此时值为2。
  • 如果现在要对s2进行自身的修改操作,先判断refCount是否大于1。若大于1,则s2要重新开辟一块空间,然后再进行修改操作,避免影响其他对象。

画板

  • s2重新开辟了一块空间,然后再修改原来的引用计数refCount,使其-1;重新开辟的空间中因为此时只有一个对象,所以引用计数refCount也是1。

总结:此方案的写时拷贝技术是同时开辟两块空间,一块用于存放自身的内容,另一块用于存放引用计数refCount,同时管理两块空间,统计当前使用此空间的对象数,当要修改当前空间的时候,进行引用计数的判断,再决定是否开辟新空间。

class String
{
public://构造函数String(char* str=""):_str(new char[strlen(str)+1]),_refCount(new int(1)){strcpy(_str, str);}//拷贝构造函数String(String& s){_str = s._str;_refCount = s._refCount;++(*_refCount);}String& operator=(const String& s){if (_str != s._str){Release();_str = s._str;_refCount = s._refCount;(*_refCount)++;}return *this;}void Release(){if (--(*_refCount) == 0){cout << "delete" << endl;delete[] _str;delete _refCount;}}~String(){Release();}void CopyOnWrite(){if (*_refCount > 1){char* tmp = new char[strlen(_str) + 1];strcpy(tmp, _str);--(*_refCount);_str = tmp;_refCount = new int(1);}}char& operator[](size_t pos){CopyOnWrite();return _str[pos];}char operator[](size_t pos) const{return _str[pos];}
private:char* _str;int* _refCount;
};

1.3 方案2

  • 开辟两块空间同时进行管理,方案2只开辟一块空间进行写时拷贝操作。

画板

  • 在对对象进行操作时,先检查引用计数的个数,然后再判断是否开辟新的空间,同时修改引用计数的值,防止空间不能释放。
  • 例如:当创建的3个对象s1、s2、s3同时指向一个空间时,再创建一个对象s4,s4的引用计数为1。

画板

再进行s3 = s4操作,此时对应的引用计数和对应的指向都需要进行修改,更改后图形如下:

画板

  • 此时对象s3指向了s4,同时原来的空间的引用计数进行-1操作 ,新指向空间的引用计数进行+1操作,而且不用开辟两块空间。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com