为什么指针在返回时不能自动转换为 unique_ptr?

Why can't a pointer be automatically converted into a unique_ptr when returning it?

让我通过一个例子来提出我的问题。

#include <memory>

std::unique_ptr<int> get_it() {
        auto p = new int;
        return p;
}

int main() {
        auto up ( get_it() );
        return 0;
}

编译失败,出现以下错误:

a.cpp:5:9: error: could not convert ‘p’ from ‘int*’ to ‘std::unique_ptr<int>’
  return p;
         ^

为什么这里没有从原始指针到唯一指针的自动转换?我应该怎么做呢?

动机:我知道使用智能指针来明确所有权应该是一种很好的做法;我从某个地方得到一个指针(我拥有),在这种情况下作为 int*,我(认为我)想要它在 unique_ptr.


如果您正在考虑发表评论或添加自己的答案,请解决 Herbert Sutter's arguments for this to be possible in proposal N4029

因为从裸指针隐式构造 unique_ptr 非常 error-prone。

只需显式构建即可:

std::unique_ptr<int> get_it() {
        auto p = new int;
        return std::unique_ptr<int>(p);
}

因为 std::unique_ptr 获得了指针的所有权,你肯定不想 deleted 意外得到你的原始指针。

如果可以的话,那么:

void give_me_pointer(std::unique_ptr<int>) { /* whatever */ }

int main() {
    int *my_int = new int;
    give_me_pointer(my_int);
    // my_int is dangling pointer
}

因为转换或强制转换需要适当的强制转换运算符(在源类型上)或构造函数(在目标类型上)。在这种情况下,must be unique_ptr 的以下构造函数:

explicit unique_ptr( pointer p );

其中有 explicit keyword. your get_it() attempts implicit conversion, which explicit prevents. Instead, you have to construct the unique_ptr explicitly, as suggested by 和@VincentSavard :

std::unique_ptr<int> get_it() {
        auto p = new int;
        return std::unique_ptr<int>(p);
}

甚至,如果我们只想说 unique_ptr 一次...

auto get_it() {
        auto p = new int;
        return std::unique_ptr<int>(p);
}

因为很危险。

使用 C++14 中的 std::make_unique()

std::unique_ptr<int> get_it()
{
    auto p = std::make_unique<int>();
    return p;
}

答案是two-fold。所有其他答案,包括 OP 的 self-answer,只解决了其中的一半。

无法自动转换指针,因为:

    来自指针的
  • unique_ptrconstructor 被声明为 explicit,因此编译器仅在显式上下文中考虑。这样做是为了防止意外的危险转换,其中 unique_ptr 可以劫持指针并在程序员不知情的情况下将其删除。通常,不仅对于 unique_ptr,将所有 single-argument 构造函数声明为 explicit 被认为是一种很好的做法,以防止意外转换。
  • return 语句被标准视为隐式上下文,因此显式构造函数不适用。 Filip Roséen 在 EWG issue 114, including links to several proposals: two versions of proposals to make return explicit by Herb Sutter (N4029, N4074), and two "responses", arguing not to do so: N4094 by Howard Hinnant and Ville Voutilainen and N4131 中反映了这个决定是否正确,正在进行讨论。经过多次讨论和投票后,该问题作为 NAD 关闭 - 不是缺陷。

目前有几种解决方法:

return std::unique_ptr<int>{p};

return std::unique_ptr<int>(p);

在c++14中,你也可以使用函数return类型的auto-deduction:

auto get_it() {
    auto p = new int;
    return std::unique_ptr<int>(p);
}

更新:为第二点的委员会问题添加了 link。