std::unique_ptr是RAII的应用吗?

Is std::unique_ptr an application of RAII?

这样描述准确吗?有道理吗?

你能保证它指向的对象在 unique_ptr 超出范围之前不会被删除 [即使你没有使用 unique_ptr] 吗?

std::unique_ptr 是 RAII,因为对象的创建也会对其进行初始化。

Are you guaranteed that the object it points to won't be deleted until the unique_ptr goes out of scope [even if you're not using the unique_ptr]?

如果你做一些假设:

  • 您不移动 unique_ptr(这会导致新移动到的位置成为将要删除的位置
  • 您不要自己删除指针或将其添加到另一个控制结构。

或者更简洁地说,是的,它会活那么久。

是的,std::unique_ptr遵循RAII设计原则。

不,std::unique_ptr 不会阻止其他代码做一些愚蠢的事情,比如在属于 unique_ptr 的指针上调用 deleteunique_ptr 本身将在其拥有的对象上调用 deleter1

  1. 超出范围

  1. unique_ptr 被重新分配(通过 operator=reset)以指向不同的对象

还可以通过移动到不同的智能指针或使用 release 成员函数来撤销 unique_ptr 对对象的所有权。这会破坏对象与 unique_ptr 之间的关联,并且 unique_ptr 将不再清理对象。


1 默认删除器将使用 deletedelete [],具体取决于目标是否具有数组类型。但是 unique_ptr 是一个模板,它的删除器可以自定义,例如 FILE* 的清理操作可以选择调用 fclose.

此功能可用于安排在 unique_ptr 超出范围时执行任意清理操作。 RAII 用于保持锁定、关闭文件等——如果仅仅因为编译器没有看到智能指针的任何未来使用而提前执行清理操作,显然会出现重大问题。幸运的是,C++ 对象生命周期规则是完全确定的(即使是同一作用域中多个自动变量的销毁顺序也有明确定义),您可以指望智能指针在其自身销毁时准确地清理其拥有的对象。

确实是RAII的一个应用。

但是你不能保证它指向的对象在 unique_ptr 超出范围之前没有被其他人删除。

例如

int* p = new int;
int* cp = p;
std::unique_ptr<int> up(p);
delete cp;

会给出未定义的行为。

std::unique_ptr 可用于 RAII,但不会阻止您执行以下操作:

#include <memory>

class Foo{};

int main()
{
    Foo* pFoo = new Foo;

    std::unique_ptr<Foo> upFoo(pFoo);
    delete pFoo; // WRONG, double deletion when upFoo's destructor is called
}

通常,使用智能指针的最佳方式是将原始指针作为其构造函数或类似make的函数传递,例如

#include <memory>

class Foo{};

int main()
{
    std::unique_ptr<Foo> upFoo(new Foo); // or make_unique in C++14
}