实现引用计数

实现代码

#include "../head.h"
#include <memory>
#include <initializer_list>

class strBlob {
public:
    typedef vector<string>::size_type size_type;
    strBlob();
    strBlob(initializer_list<string> il);
    strBlob(const strBlob &sb);

    strBlob& operator=(const strBlob &rhs);

    size_type size() const {return data->size();}
    bool empty() const {return data->empty();}
    size_t get_use() {return *use;}
    void push_back(const string &t) {data->push_back(t);}

    void pop_back();
    string& front() const;
    string& back() const;

    ~strBlob();
private:
    vector<string> *data;
    void check(size_type i, const string &msg) const;
    size_t *use;
};



strBlob::strBlob() : 
    data(new vector<string>()), use(new size_t(1)) { }

strBlob::strBlob(initializer_list<string> il) :
    data(new vector<string>(il)), use(new size_t(1)) { }

strBlob::strBlob(const strBlob &sb) : 
    data(sb.data), use(sb.use) {++*use;}



strBlob& strBlob::operator=(const strBlob &rhs) {
    ++*rhs.use;
    if (--*use == 0) {
        delete data;
        delete use;
    }
    data = rhs.data;
    use = rhs.use;
    return *this;
}



void strBlob::check(size_type i, const string &msg) const {
    if (i >= data->size())
        throw out_of_range(msg);
}

void strBlob::pop_back() {
    check(0, "pop_back on empty strBlob");
    data->pop_back();
}

string& strBlob::front() const {
    check(0, "front on empty strBlob");
    return data->front();
}

string& strBlob::back() const {
    check(0, "back on empty strBlob");
    return data->back();
}



strBlob::~strBlob() {
    if (--*use == 0) {
        delete data;
        delete use;
    }
}



int main(int argc, char** argv) {
    strBlob a = {"hello", "world"};
    a.pop_back();
    strBlob b = a;
    b.push_back("fromb");
    cout << "The last word in a: " << a.back() << endl;
    cout << "The first word in b: " << b.front() << endl;

    strBlob c = b;
    cout << "After c = b; there are " << a.get_use() << " use from a now" << endl;

    c = {"ni", "hao"};
    cout << "After assign value to c, there are " << a.get_use() << " use from a now" << endl;
    return 0;
}

输出

The last word in a: fromb
The first word in b: hello
After c = b; there are 3 use from a now
After assign value to c, there are 2 use from a now

这是从《C++ primer》13-27的习题引申出来的代码,将前文strBlob类给做了一些改编,使用这串代码可以直观的感受到引用计数的工作过程,他们可以共享底层的数据,且实现了类似智能指针的效果,代码的输出也完全符合预期

这里重点关注的就是三个地方拷贝构造函数拷贝赋值运算符析构函数,要确保拷贝行为的引用计数增减正确,析构时正确的释放内存

赋值语句

通过在成员函数中打印内容弄清楚了c = {"ni", "hao"};这条赋值语句工作的整个过程
1 赋值号右边的内容通过使用列表构造函数生成了一个临时的类的对象,此时它的引用计数为一
2 临时的类的对象通过拷贝赋值运算符给c赋值,此时进入到拷贝赋值运算符中

strBlob& strBlob::operator=(const strBlob &rhs) {
    ++*rhs.use;
    if (--*use == 0) {
        delete data;
        delete use;
    }
    data = rhs.data;
    use = rhs.use;
    return *this;
}
  • 此时临时的类的对象就是rhs,它的引用计数加一,此时它的引用计数为二
  • if (--*use == 0)这条判断减减的use是对象a中的引用计数use,行为类似于书中给shared_ptr赋予一个新值,计数器递减
  • 然后就是把临时的类的对象的数据成员全部赋值给c,包括对应的引用计数,依旧是二

3 到这里整条赋值语句就已完成,接着就要把那个临时的类的对象销毁

strBlob::~strBlob() {
    if (--*use == 0) {
        delete data;
        delete use;
    }
}
  • if (--*use == 0)这条判断的use的值为二,减减后变为一,一切都如预料的那样

所以,整条赋值语句完成后就正常的给c赋了新值,且它的引用计数为一,对于它脱离了a的数据,a的引用计数也正常的减了一

转载于:https://www.cnblogs.com/Anthony-ling/p/10696540.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值