- 定义在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置为空
- 注意!我们不能拷贝或者赋值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;
}
- 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共享对象
}
- 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;
}
}