一个unique_ptr“拥有”它所指向的对象。与shared_ptr不同,某个时刻只能有一个unique_ptr指向一个给定的对象。当unique_ptr被销毁时,它所指向的对象也被销毁。
当我们定义一个unique_ptr时,需要将其绑定到一个new返回的指针上。类似shared_ptr,初始化unique_ptr必须采用直接初始化形式:
unique_ptr<double> p1; //可以指向一个double的shared_ptr
unique_ptr<int> p2(new int(42)); //p2指向一个值为42的int
由于unique_ptr拥有它指向的对象,因此unique_ptr不支持普通的拷贝或赋值操作:
unique_ptr<string> p1(new string("Love"));
unique_ptr<string> p2(p1); //错误:unique_ptr不支持拷贝
unique_ptr<string> p3;
p3 = p2; //错误:unique_ptr不支持赋值
|
---|
unique_ptr<T> sp | 空智能指针,可以指向类型为T的对象 | p | 将p用作一个判断条件,若p指向一个对象,则为true | *p | 解引用p,获得它指向的对象 | p->mem | 等价于(*p).mem | p.get() | 返回p保存的指针。要小心使用,若智能指针释放了其对象,返回的指针所指向的对象也就消失了 | p.swap(q) | 交换p和q的指针 | unique_ptr<T> u1 | 空unique_ptr,可以指向类型为T的对象 | unique_ptr<T, D> u2 | 使用一个类型为D的可调用对象来释放它的指针 | unique_ptr<T, D> u(d) | 使用一个类型为D的可调用对象d代替delete | u.reset() | 释放u指向的对象 | u.reset(q) | 如果提供了内置指针q,令u指向这个对象,否则将u值为空 | u = nullptr | 释放u指向的 | u.release() | u放弃对指针的控制权,返回指针,并将u置空 |
虽然我们不能拷贝或赋值unique_ptr,但可以通过调用release或reset将指针的所有权从一个unique_ptr转移给另一个unique:
//将所有权从p1转移给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和它原来管理的对象间的联系。release返回的指针通常被用来初始化另一个智能指针或给另一个智能指针赋值。
p2.release(); //错误:p2不会释放内存,而且我们丢失了指针
auto p = p2.release(); //正确,当我们必须记得delete(p)
传递unique_ptr参数和返回unique_ptr
不能拷贝unique_ptr的规则有一个例外:我们可以拷贝和赋值一个将要被销毁的unique_ptr.常见的例子是从函数返回一个unique_ptr(移动):
unique_ptr<int> clone(int p)
{
// 正确:从int*创建一个unique_ptr<int>
return unique_ptr<int>(new int(p));
}
unique_ptr<int> clone(int p)
{
// 正确:返回局部对象的拷贝
unique_ptr<int> ret(new int(p));
return ret;
}
向unique_ptr传递删除器
?重载一个unique_ptr中的删除器会影响到unique_ptr类型以及如何构造该类型的对象。我们必须在
?尖括号中unique_ptr指向类型之后提供删除器类型,在创建或reset一个这种unique_ptr类型的对象时,必须提供一个指定类型的可调用对象(删除器):
//p指向一个类型为objT的对象,并使用一个类型为delT的对象释放objT对象
//它会调用一个名为fcn的delT类型对象
unique_ptr<objT, delT> p(new objT, fcn);
示例
unique_ptr<connection, decltype(end_connection)*> p(&c, end_connection);
本例中,我们使用了decltype来指明函数指针类型,由于decltype(end_connection)返回一个函数类型,所以我们必须添加一个*来指出我们正在使用该类型的一个指针
|