智能指针之unique_ptr

概述

与shared_ptr不同,某个时刻只能有一个unique_ptr指向一个给定对象。当unique_ptr被销毁时,它所指向的对象也被销毁。同时,unique_ptr也没有类似于make_shared的标准库函数,当我们定义一个unique_ptr时,需要将其绑定到一个new返回的指针。因此初始化unique_ptr需要使用直接初始化的形式。例如:

    unique_ptr<double> p(new double(3.14));    // p指向一个值为3.14的double

并且,由于一个unique_ptr“拥有”(唯一指向)其指向的对象,所以unique_ptr不支持拷贝或者赋值操作:

    unique_ptr<string> p1(new string("southernEast"));
    unique_ptr<string> p2(p1);    // 错误:不能拷贝
    unique_ptr<string> p3;
    p3 = p2;                      // 错误:不能赋值

虽然我们不能拷贝或者赋值一个unique_ptr,但是我们能够通过使用release或reset函数来将一个非const的unique_ptr的指针所有权转移给另一个unique_ptr。例如:

    unique_ptr<string> p2(p1.realease());  // 将p1的指针所有权转移给p2,release将p1置空
    unique_ptr<string> p3(new string("southernEast"));
    p2.reset(p3.release());                // reset释放了p2原来指向的内存,并将p3指针的所有权转移给p2

这里需要注意的是,reset函数会释放其原来指向的对象,而release函数仅仅只是返回当前保存的指针,并将当前保存的指针值置为空,不会释放其原来指向的对象(形象地说就是“放弃控制权”)。

常用操作 用法说明
unique_ptr< T > u 空的指向类型为T的对象的unique_ptr
unique_ptr< T, D > u 使用一个类型为D的可调用对象释放它的指针
unique_ptr< T, D > u(d) 使用类型为D的对象d来代替delete
u = nullptr 释放u指向的对象,将u置为空
u.release() 放弃对指针的控制权,返回指针,并将u置为空
u.reset() 释放u指向的对象
u.reset(q) 将u指向内置指针q
u.reset(nullptr) 将u置为空

传递unique_ptr参数和返回unique_ptr

不能拷贝unique_ptr的规则有一个例外:我们可以拷贝或赋值一个将要被销毁的unique_ptr,例如从函数返回的uinque_ptr:

unique_ptr<int> clone1(int p) {
    return unique_ptr<int>(new int(p));    // 正确
}
unique_ptr<int> clone2(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);
posted @ 2020-03-21 12:28  southernEast  阅读(383)  评论(0编辑  收藏  举报