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

li9yvcax  于 2023-06-07  发布在  其他
关注(0)|答案(5)|浏览(297)

考虑以下程序:

#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

j13ufse2

j13ufse21#

答案是双重的。所有其他的答案,包括OP的自我回答,只解决了一半。
无法自动转换指针,因为:

  • unique_ptrconstructor从一个指针被声明为explicit,因此编译器只在显式上下文中考虑。这样做是为了防止意外的危险转换,其中unique_ptr可以劫持指针并在程序员不知情的情况下删除它。一般来说,不仅对于unique_ptr,将所有单参数构造函数声明为explicit以防止意外转换也被认为是一个很好的实践。
  • return语句被标准视为隐式上下文,因此显式构造函数不适用。目前正在讨论这一决定是否正确,反映在EWG问题114中,包括与几项提案的链接:Herb Sutter(N4029N4074)提出的两个版本的建议,以及两个“回应”,争论不要这样做:N4094由霍华德Hinnant和Ville Voutilainen撰写,N4131由Filip Roséen撰写。经过几次讨论和民意调查,该问题被关闭为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);
}

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

yhived7q

yhived7q2#

因为从裸指针隐式构造unique_ptr非常容易出错。
只需要显式地构造它:

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

8gsdolmq3#

因为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
}
gblwokeq

gblwokeq4#

因为转换或强制转换需要适当的强制转换运算符(在源类型上)或构造函数(在目标类型上)。在本例中,它是must be,下面是unique_ptr的构造函数:

explicit unique_ptr( pointer p );

它有explicit keyword。您的get_it()尝试隐式转换,这是explicit阻止的。相反,你必须显式地构造unique_ptr,正如@Stas和@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);
}
g0czyy6m

g0czyy6m5#

因为它很危险。
使用来自C++14的std::make_unique()

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

相关问题