C++ Primer第十二章④
C++ Primer
更多内容戳这里
动态内存
我们讲了那么多,只是讲了三个智能指针中的一个shared_ptr,还有两个呢:unique_ptr和weak_ptr(是不是很烦)学好了第一个,那后面两个其实也还算简单,下面我们分别来介绍。
unique_ptr
一个unique_ptr独有它所指向的对象,与shared_ptr(人尽可夫)不同,unique_ptr比较霸道总裁,某个时刻只能有一个unique_ptr指向给定的对象,所以啊,当unique_ptr被销毁时,它所指向的对象也被销毁。
unique_ptr p1;
unique_ptr pt(new int(42));
我们先来看看unique_ptr独有的一些操作(shared)ptr那些它都行):
这里厉害了:unique_ptr不支持普通的拷贝或赋值(因为它独有啊,霸道啊),拷贝给你了不是有两个指向那个内存了吗?
不过啊,我们可以调用一些函数来将所有权从一个unique_ptr(非const)转移给另一个unique_ptr:
unique_ptr p1(new string("hello"));
unique_ptr p2(p1.release()); //p2被初始化为p1原来保存的指针,而将p1置空
unique_ptr p3(new string("hi"));
p2.reset(p3.release); //跟上面效果一样,但形式不同,因为这里不是初始化了,算是赋值
p2.release(); //我们把指针置空了,却没有释放内存。。。
传递unique_ptr和返回unique_ptr
不能拷贝unique_ptr有例外:可以拷贝或赋值一个将要被销毁的unique_ptr:
//函数返回一个unique_ptr
unique_ptr clone(int p)
{
return unique_ptr(new int(p)); //正确:int*隐式转换到unique_ptr
}
//返回一个局部对象的拷贝
unique_ptr Clone(int p)
{
unique_ptr ret(new int(p));
return ret;
}
对于上面这两个函数,编译器很聪明,它知道要返回的对象将要被销毁,所以它会执行一种特殊的拷贝(以后再介绍)。
向unique_ptr传递删除器
unique_ptr默认还是delete删除,也支持自定义,但是它这个自定义很特殊(以后再解释原因),我们来看一下格式(比较复杂的):
unique_ptr p (new objT, fcn);
//p指向一个类型为objT的对象,并使用类型为delT的对象释放objT对象
//怎么释放呢?它会调用delT类型对象fcn
weak_ptr
一听名字就很弱,它其实是来占shared_ptr便宜的。
weak_ptr指向由shared_ptr管理的对象,但不改变引用计数 它的操作如下图:
auto p = make_shared(24);
weak_ptr wp(p); //创建weak_ptr要用shared_ptr来初始化它
//由于对象可能不存在,我们在用weak_ptr访问时要调用lock函数来检查对象是不是还在
if(shared_ptr np = wp.lock()) //如果对象存在,lock返回该对象的shared_ptr
{
//在这用np访问是安全的
}
我们可能觉得这个weak_ptr没啥大用,那我们就来举个例子,说明它还是有用的。
核查指针类
还记得我们最开始的StrBolb类吗,我们要为它定义一个指针类StrBlobPtr,可以指向它的对象,该指针会保存一个weak_ptr,指向StrBlob的data成员(在初始化时给它的)。
为什么要用weak_ptr呢?因为它不会影响一个给定的StrBlob所指向的vector的生存期,但是它可以阻止用户访问一个不存在的vector:
class StrBlobPtr
{
public:
StrBlobPtr() : curr(0){}
StrBlobPtr(StrBlob &a, size_t sz = 0) : wptr(a.data), curr(sz){}
private:
shared_ptrstring> check(size_t, const string&) const; //检查下标合法性
weak_ptr> wptr; //指向vector的弱指针
size_t curr; //记录在数组中的当前位置
};
我们要定义一下check函数,它不仅要检查下标的合法性,还要负责检查指向的vector还在不在:
shared_ptr> StrBlobPtr::check(size_t i, const string &msg) const
{
auto ret = wptr.lock; //vector还在吗
if(!ret)
{
throwruntime_error("空悬指针了啊");
}
if(i >= ret->size())
{
throw out_of_range(msg);
}
return ret; //成功的话返回指向vector的shared_ptr
}
#C++工程师#