为什么 C++ 需要 std::make_unique 而不是转发的 unique_ptr 构造函数?

Ang*_*ros 0 c++ unique-ptr

不会new operator这里那样问。请仔细阅读问题。

我想知道为什么我们需要特殊函数make_unique而不是 unique_ptr 的特殊构造函数。

unique_ptr可以使用这样的构造函数来使make_unique不必要的:

template<typename T, typename ...TArgs>
unique_ptr::unique_ptr(TArgs&&... args)
        : inner_ptr(new T(std::forward(args)...))
{}
Run Code Online (Sandbox Code Playgroud)

小智 6

这有几个原因。

第一个与 C++ 的历史有关。在 C++17 之前,构造函数没有异常安全性,因此请执行以下操作:

some_func(std::unique_ptr<T1>(), std::unique_ptr<T2>())
Run Code Online (Sandbox Code Playgroud)

如果 T1 的构造函数抛出异常,则会泄漏内存,因为 C++ 标准不要求(在本例中第一个 unique_ptr)应该释放其内存。自 C++17 以来,情况不再如此

其次,它允许“从不使用new”的更一般规则,如果没有,make_unique则“从不使用,new除非使用unique_ptrshared_ptr

此外,还有一个额外的好处,即没有多余的类型,就像您必须执行的构造函数一样:

auto p = std::unique_ptr<T>(new T());
Run Code Online (Sandbox Code Playgroud)

列出T两次,这在长类型名称的情况下尤其难看。这样make_unique缩短到

auto p = std::make_unique<T>();
Run Code Online (Sandbox Code Playgroud)

  • *“在 C++17 之前,构造函数没有异常安全性”* - 您的示例不适用于 C++17 之前的问题。像 `std::unique_ptr&lt;T1&gt;(new T1), std::unique_ptr&lt;T2&gt;(new T2)` 之类的东西是不安全的,但这不是OP所建议的。“new”发生在“unique_ptr”的**内部**,作为其执行的一部分。就像常规函数调用一样,不能有交错。 (3认同)