C++基础 - 智能指针 weak_ptr 用途之核查指针类

weak_ptr 是一种不控制所指向对象生存期的智能指针,它指向有一个 shared_ptr 管理的对象。将一个 weak_ptr 绑定到 shared_ptr 不会改变 shared_ptr 的引用计数。一旦最后一个指向对象的 shared_ptr 被销毁,对象就会被释放。即使有 weak_ptr 指向对象,对象也还是会被释放。

因此不能直接用 weak_ptr 访问对象,而必须调用 lock 检查其指向的对象是否仍存在。如果存在,lock 返回一个指向共享对象的 shared_ptr。因此,只要此 shared_ptr 存在,它所指向的底层对象就会一直存在。

使用 sared_ptr 实现的对象共享底层数据类 StrBlob

class StrBlobPtr;
class StrBlob {    
public:
    friend class StrBlobPtr;
    // 返回指向首元素和尾后元素的 StrBlobPtr
    StrBlobPtr begin();
    StrBlobPtr end();

    using size_type = vector<string>::size_type;

    StrBlob():data(make_shared<vector<string>>()){}
    StrBlob(initializer_list<string> il):data(make_shared<vector<string>>(il)) {}
    // 类属性
    size_type size() const {
        return data->size();
    }
    bool empty() const {
        return data->empty();
    }
    // 添加和删除元素
    void push_back(const string& str) {
        data->push_back(str);
    }
    void pop_back() {
        check(0, "pop_back on empty StrBlob");
        data->pop_back();
    }

    // 访问元素,非常量版本
    string& front() {
        check(0, "front on empty StrBlob");
        return data->front();
    }
    string& back() {
        check(0, "back on empty StrBlob");
        return data->back();
    }

    // 访问元素,const版本
    const string& front() const {
        check(0, "front on empty StrBlob");
        return data->front();
    }
    const string& back() const {
        check(0, "back on empty StrBlob");
        return data->back();
    }

    // print
    void print(const string& msg) const {
        cout << msg << "[ ";
        for(size_type i=0; i<size(); i++) {
            cout << data->at(i) << " ";
        }
        cout << "]";
        cout << endl;
    }
private:
    shared_ptr<vector<string>> data;
    // 核查索引是否在有效范围内
    void check(size_type i, const string& msg) const {
        if( i >= size() ) {
            throw out_of_range(msg);
        }
    }
};

为 StrBlob 定义一个伴随指针类,保存一个 weak_ptr, 指向 StrBlob 的 data 成员。

class StrBlobPtr {
public:
    StrBlobPtr():curr(0) {}
    StrBlobPtr(StrBlob& b, size_t cur=0):wptr(b.data),curr(cur) {}

    // 解引用
    string& deref() const {
        auto ret = check(curr, "dereference past end");
        return (*ret)[curr];
    }
    // 自增
    StrBlobPtr& incr() {
        check(curr, "increase past end of StrBlobPtr");
        ++curr;
        return *this;
    }
private:
    // 核查,若成功,返回一个指向vector的shared_ptr
    shared_ptr<vector<string>> check(size_t i, const string& msg) const {
        auto ret = wptr.lock();
        if( !ret ) {
            throw runtime_error("unbound StrBlobPtr");
        }
        if( i >= ret->size() ) {
            throw out_of_range("msg");
        }
        return ret;
    }

    weak_ptr<vector<string>> wptr;  // 指向vector
    size_t curr;                    // 在数组中的位置
};

StrBlobPtr StrBlob::begin() {
    return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end() {
    auto ret = StrBlobPtr(*this, data->size());
    return ret;
}

测试代码

void WeakPtrTest1() {
    StrBlob sb1({"apple", "banalan", "juce"});
    {
        StrBlob sb2 = sb1;
    }

    auto iter = sb1.begin();
    auto itere = sb1.end();

    string str = iter.deref();
    iter.incr();
    str = iter.deref();
    iter.incr();
    str = iter.deref();
    iter.incr();
    str = iter.deref();

    return;
}

C++ primer中文版 第五版 12章

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值