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



请考虑以下程序:

#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.

<小时 />

如果您正在考虑评论或添加自己的答案,请在提案 N4029 中解决 Herbert Sutter 的论点。

答案是双重的。所有其他答案,包括OP的自我回答,都只解决了其中的一半。

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

  • unique_ptr的构造函数从指针被声明为explicit,因此编译器只在显式上下文中考虑。这样做是为了防止意外的危险转换,unique_ptr可以在程序员不知情的情况下劫持指针并将其删除。一般来说,不仅对于unique_ptr,将所有单参数构造函数声明为explicit以防止意外转换被认为是一种很好的做法。
  • return 语句被标准视为隐式上下文,因此显式构造函数不适用。如果这个决定是正确的,正在进行讨论,反映在EWG第114期中,包括几个提案的链接:Herb Sutter(N4029,N4074)明确return的两个提案版本,以及两个"回应",认为不要这样做:Howard Hinnant和Ville Voutilainen的N4094和Filip Roséen的N4131。经过几次讨论和民意调查,该问题被关闭为NAD - 不是缺陷。

目前,有几种解决方法:

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

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

在 c++14 中,您也可以使用函数返回类型的自动推导:

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

更新:为第二点添加了指向委员会问题的链接。

因为从裸指针隐式构造unique_ptr非常容易出错。

只需显式构造它:

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

因为std::unique_ptr拥有指针的所有权,而且您绝对不希望意外地获得原始指针delete d。

如果可能的话,那么:

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
}

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

explicit unique_ptr( pointer p );

其中有显式关键字。 您的get_it()尝试隐式转换,这explicit阻止。相反,您必须按照 @Stas 和 @VincentSavard 的建议显式构造unique_ptr

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;
}

相关内容

  • 没有找到相关文章

最新更新