1. unique_ptr
某个时刻只能由一个unique_ptr指向一个给定对象
定义一个unique_ptr时,需要将其绑定到一个new返回的指针上。类似shared_ptr,初始化unique_ptr必须采用直接初始化形式。
unique_ptr<double> p1;//可以指向一个double的unique_ptr
unique_ptr<int> p2(new int(42));//p2指向一个值为42的int
unique_ptr不支持普通的拷贝或赋值
unique_ptr<string> p1(new string("Stegosaurus"));
unique_ptr<string> p2(p1);//错误:unique_ptr不支持拷贝
unique_ptr<string> p3;
p3 = p2;//错误:unique_ptr不支持赋值
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) |
虽然不能拷贝或赋值unique_ptr,但可以通过调用release或reset将指针的所有权从一个(非const)unique_ptr转移给另一个unique。
//将所有权从p1(指向string Stegosaurus)转移给p2
unique_ptr<string> p2(p1.release());//release将p1置为空
unique_ptr<string> p3(new string("Trex"));
//将所有权从p3转移给p2
p2.reset(p3.release());//reset释放了p2原来指向的内存
release成员返回unique_ptr当前保存的指针并将其置为空,因此p2被初始化为p1原来保存的指针,而p1被置为空。
reset成员接受一个可选的指针参数,令unique_ptr重新指向给定的指针。如果unique_ptr不为空,它原来指向的对象被释放。因此上例中,对p2调用reset释放了用“Stegosaurus”初始化的string所使用的内存,将p3对指针的所有权转移给p2,并将p3置为空。
如果不用另一个智能指针来保存release返回的指针,我们的程序就要负责资源的释放
p2.release();//错误:p2不会释放内存,而且我们丢失了指针
auto p = p2.release;//正确:但我们必须记得delete(p)
2. 传递unique_ptr参数和返回unique_ptr
不能拷贝unique_ptr的规则有一个例外:我们可以拷贝或赋值一个将要被销毁的unique_ptr。比如从函数返回一个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));
//...
return ret;
}
编译器知道要返回的对象将要被销毁,在此情况下,编译期执行一种特殊的拷贝。