引用计数的写时拷贝

提起写时拷贝,自然就得说到深浅拷贝的问题了,到底什么是深浅拷贝呢?深浅拷贝到底都做了什么?


浅拷贝:浅拷贝是位拷贝,使俩个对象指向了同一块空间,并没有重新开辟一块新的空间。一个对象如果对这块空间进行了改变,则另一个对象也会跟着改变。



深拷贝:深拷贝就是另外开辟一个空间出来,将原有的数据全部复制一份放到新的空间中,然后把新的空间交给你,经过深拷贝的对象和原有的对象不会指向同一空间,所以一个对象的改变不会影响另外一个空间。



引用计数: 加入引用计数的目的是为了解决类中的浅拷贝问题,例如一个string类中,如果拷贝构造函数是浅拷贝,如果没有引入引用计数的话一块空间则会被释放多次从而导致程序崩溃,加入引用计数后,当计数减减到0的时候再对空间进行释放,这样就有效的防止了程序的崩溃。


上述的引用计数虽然解决了空间释放的问题,但是我们有时候需要改变一个对象,但是期望在改变一个对象的时候不会影响到其他对象,这个时候我们就需要引入引用计数的写时拷贝了,当我们使用拷贝构造或者赋值运算符重载时,俩个对象指向了同一块空间,但是当我们需要修改其中一个对象时,此时就会为需要改变的对象开辟一个独立的空间,这个时候这个对象的改变就不会影响其他的空间了。


写时拷贝有俩种实现方法,一种是上面的单独定义一个recount,还有一种是在字符串开头的4个空间处引入。

写时拷贝在需要开辟空间时再开辟,不需要的时候多个对象公用一块空间,充分利用了空间。

0
 
0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个可能的实现: ```c++ #include <string> #include <iostream> class RefCount { private: int count; int weakCount; public: RefCount() : count(0), weakCount(0) {} void addRef() { count++; } void release() { count--; if (count == 0) delete this; } void addWeakRef() { weakCount++; } void releaseWeak() { weakCount--; if (weakCount == 0 && count == 0) delete this; } }; class KString { private: std::string* str; RefCount* refCount; public: KString() : str(new std::string()), refCount(new RefCount()) { refCount->addRef(); } KString(const char* s) : str(new std::string(s)), refCount(new RefCount()) { refCount->addRef(); } KString(const std::string& s) : str(new std::string(s)), refCount(new RefCount()) { refCount->addRef(); } KString(const KString& other) : str(other.str), refCount(other.refCount) { refCount->addRef(); } ~KString() { refCount->release(); } KString& operator=(const KString& other) { if (this != &other) { refCount->release(); str = other.str; refCount = other.refCount; refCount->addRef(); } return *this; } char& operator[](int i) { if (refCount->count > 1) { refCount->release(); str = new std::string(*str); refCount = new RefCount(); refCount->addRef(); } return (*str)[i]; } const char& operator[](int i) const { return (*str)[i]; } }; int main() { KString s1("hello"); KString s2 = s1; std::cout << s1[1] << std::endl; // 'e' std::cout << s2[1] << std::endl; // 'e' s1[1] = 'a'; std::cout << s1[1] << std::endl; // 'a' std::cout << s2[1] << std::endl; // 'e' return 0; } ``` 这个实现中,KString类包含一个指向std::string的指针和一个指向RefCount的指针。RefCount类用于记录当前对象的引用计数和弱引用计数,当引用计数为0会自动删除对象。KString类的默认构造函数和带参构造函数会创建一个新的std::string对象和一个新的RefCount对象,并将引用计数加一。拷贝构造函数和赋值运符会将指针和引用计数从另一个KString对象复制过来,并将引用计数加一。KString类还重载了[]运符,当引用计数大于1会进行拷贝,即复制一个新的std::string对象并将引用计数设为1,然后再进行修改。这样可以确保只有当一个KString对象确实需要修改才会进行拷贝,从而避免了不必要的性能开销。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值