c++笔记-动态内存(unique_ptr & weak_ptr)

  1. 定义在unique_ptr上的独有操作
unique_ptr<T> u1        空unique_ptr,可以指向类型为T的对象。u1会使用delete来释放它的指针
unique_ptr<T, D> u2     u2会使用一个类型为D的可调用对象来释放它的指针
unique_ptr<T, D> u(d)   空unique_ptr,指向类型为T的对象,用类型为D的对象d代替delete

u = nullptr     释放u所指向的对象,将u置为空
u.release()     u放弃对指针的控制权,返回指针,并将u置为空

u.reset()       释放u指向的对象
u.reset(q)      如果提供了内置的指针q,令u指向这个对象;否则u置为空
u.reset(nullptr)    u置为空
  1. 注意!我们不能拷贝或者赋值unique_ptr,但是可以使用release或者reset将指针的所有权从一个(非const)unique_ptr转移给另一个unique
unique_ptr<string> p1(new string("Test"));  //使用直接初始化
unique_ptr<string> p2(p1.release());        //p1放弃使用权,返回的指针给p2初始化

unique_ptr<string> p3(new string("New"));   //p3使用直接初始化
p2.reset(p3.release());     //p2使用reset更改指针指向对象

有一个例外:我们可以拷贝或赋值一个将要被销毁的unique_ptr对象——用作函数的返回
unique_ptr<int> clone(int p)
{
    return unique_ptr<int>(new int(p));
}
//还可以返回一个局部对象的拷贝
unique_ptr<int> clone(int p)
{
    unique_ptr<int> ret(new int(p));
    //使用ret
    return ret;
}
  1. weak_ptr指针不控制所指向的对象的生存周期,即将一个weak_ptr绑定到shared_ptr上,不会增加shared_ptr指向对象的引用次数,因此称为“弱共享智能指针”
weak_ptr上的操作
weak_ptr<T> w       定义一个指向T类型的空weak_ptr
weak_ptr<T> w(sp)   与sp指向同一个对象

w = p           p对象可以是一个shared_ptr或weak_ptr。赋值后w与p共享对象
w.reset()       将w置为空
w.use_count()   与w共享shared_ptr的数据
w.expired()     若w.use_count()为0,则返回true,即无shared_ptr与w共享;否则返回false
w.lock()        若w.expired()返回true,返回一个空的shared_ptr;否则返回一个指向w的对象的shared_ptr

当我们创建一个ptr时,要用一个shared_ptr来初始化它
auto p = make_shared<int>(42);
weak_ptr<int> wp(p);    //wp弱共享p;p的引用计数并未改变
//由于不能确定weak_ptr指向的对象是否存在,因此必须调用lock检查
if(shared_ptr<int> np = wp.lock())
{
    //如果np不为空,则条件成立
    //在if中,np与p共享对象
}
  1. StrBlobPtr伴随类例子
//对于访问一个不存在的元素,StrBlobPtr抛出一个异常
class StrBlobPtr
{
public:
    StrBlobPtr() : curr(0) { }
    StrBlobPtr(StrBlob &a, size_t sz = 0) : wptr(a.data), curr(sz) { }
    std::string& deref() const;
    StrBlobPtr& incr();     //前缀递增
private:
    //如果检查成功,check返回一个指向vector的shared_ptr
    std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string&) cosnt;
    //保存一个weak_ptr,意味着底层vector可能被销毁
    std::weak_ptr<std::vector<std::string>> wptr;
    std::size_t curr;
}

StrBlobPtr中有两个数据成员wptr和curr
wptr,或者为空,或者指向一个StrBlob类中的vector
curr,保存当前对象所表示的元素下标。

默认构造函数生成一个空的StrBlobPtr。
其构造函数的初始值列表将curr显示初始化为0,将wptr隐式初始化为一个空的weak_ptr。
第二个构造函数,接受一个StrBlob引用和可选参数(索引值).
#注意#
我们不能将StrBlobPtr绑定到一个const StrBlob对象上,因为构造函数接受的不是const StrBlob对象
StrBlobPtr中的check成员与StrBlob中的同名成员不同,它还要检查vector是否存在
std::shared_ptr<std::vector<std::string>> check(std::size_t i, const std::string& msg) const
{
    auto ret = wptr.lock();
    if(!ret)
        throw std::runtime_error("unbound StrBlobPtr");
    if(i >= ret->size())
        throw std::out_of_rang(msg);
    return ret; //当满足条件后,返回指向vector的shared_ptr
}
定义deref和incr函数用来解引用和递增StrBlobPtr
std::string& StrBlobPtr::deref() const
{
    auto p = check(curr, "deference past end");
    return (*p)[curr];  //如果check成功了,p就是指向StrBlob所指向的vector。解引用后访问元素
}
StrBlobPtr& StrBlobPtr::incr()
{
    //如果curr已经指向容器的尾后位置,就不能再递增它
    check(curr, "increment past end of StrBlobPtr");
    ++curr; //推进当前位置
    return *this;
}
当然,为了访问data成员,我们的指针类必须声明为StrBlob的friend。同时还要定义StrBlob类的begin和end操作,返回一个指向它自身的StrBlobPtr:
//对于StrBlob中的友元声明来说,此前置声明是必要的
class StrBlobPtr;
class StrBlob
{
    friend class StrBlobPtr;
    //其他与原StrBlob类一致
    StrBlobPtr begin() { return StrBlobPtr(*this); }
    StrBlobPtr end()
    {
        auto ret = StrBlobPtr(*this, data->size());
        return ret;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值