C++ 为什么可以';返回指针时,指针是否会自动转换为唯一的\u ptr?

C++ 为什么可以';返回指针时,指针是否会自动转换为唯一的\u ptr?,c++,pointers,c++11,smart-pointers,explicit,C++,Pointers,C++11,Smart Pointers,Explicit,让我通过一个例子提出我的问题 #include <memory> std::unique_ptr<int> get_it() { auto p = new int; return p; } int main() { auto up ( get_it() ); return 0; } #包括 std::unique_ptr get_it(){ 自动p=新整数; 返回p; } int main(){ 自动启

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

#include <memory>

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

int main() {
        auto up ( get_it() );
        return 0;
}
#包括
std::unique_ptr get_it(){
自动p=新整数;
返回p;
}
int main(){
自动启动(get_it());
返回0;
}
编译失败,出现以下错误:

a.cpp:5:9: error: could not convert ‘p’ from ‘int*’ to ‘std::unique_ptr<int>’
  return p;
         ^
a.cpp:5:9:错误:无法将“p”从“int*”转换为“std::unique\u ptr”
返回p;
^
为什么这里没有从原始指针到唯一指针的自动转换?我该怎么做呢

动机:我理解使用智能指针来明确所有权应该是一个很好的实践;我从某处得到了一个指针(我自己的),在本例中是
int*
,我(想我)希望它是
唯一的\u ptr



如果您正在考虑评论或添加自己的答案,请注明。

,因为从裸指针隐式构造
unique\u ptr
非常容易出错

只需明确地构造它:

std::unique_ptr<int> get_it() {
        auto p = new int;
        return std::unique_ptr<int>(p);
}
std::unique_ptr get_it(){
自动p=新整数;
返回std::unique_ptr(p);
}

因为
std::unique\u 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
}
void-give_-me_指针(std::unique_-ptr){/*whatever*/}
int main(){
int*my_int=新int;
给我一个指针(my int);
//我的智力是悬空的指针
}

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

explicit unique_ptr( pointer p );
这是最重要的。您的
get_it()
尝试隐式转换,而
explicit
阻止隐式转换。相反,您必须显式地构造
唯一的\u ptr
,正如和@VincentSavard所建议的:

std::unique_ptr<int> 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;
}
std::unique_ptr get_it()
{
自动p=std::使_唯一();
返回p;
}

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

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


  • 指针中的
    唯一\u ptr
    声明为
    显式
    ,因此编译器仅在显式上下文中考虑。这样做是为了防止意外的危险转换,
    unique\u ptr
    可以劫持指针并在程序员不知情的情况下删除它。一般来说,不仅对于
    unique\u ptr
    ,将所有单参数构造函数声明为
    explicit
    以防止意外转换也是一种良好的做法
  • 标准将return语句视为隐式上下文,因此显式构造函数不适用。关于这一决定是否正确的讨论正在进行中,反映在中,包括与几个提案的链接:Herb Sutter(,)提出的两个版本的关于使
    return
    明确化的提案,以及两个“回复”,他们辩称不这样做:Howard Hinnant和Ville Voutilainen以及Filip Roséen。经过几次讨论和民意调查,这一问题最终以全国广告部的名义解决了——这不是一个缺陷
目前,有几种变通方法:

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

返回std::unique_ptr(p);
在c++14中,还可以使用函数返回类型的自动推断:

auto get_it() {
    auto p = new int;
    return std::unique_ptr<int>(p);
}
自动获取它(){
自动p=新整数;
返回std::unique_ptr(p);
}


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

因为那时的事情像
intx;return&x将编译。您可以从指针创建一个,例如
std::unique\u ptr(p)
。不,您返回的是
p
,它的类型是
int*
,而不是
std::unique\u ptr
。可能您不了解
auto
的功能。这就是编译器不编译此代码的原因。您的问题是“为什么不将
p
隐式转换为
std::unique_ptr
?”因为定义了从
double
int
的隐式转换。您混合了不同的概念。我不能说我理解返回
唯一\u ptr
的函数如何容易出错。你能再详细一点吗?例如,
foo(unique_ptr p){}
在这种情况下可以窃取一个传递的裸指针,并销毁该对象。你的示例不涉及返回unique_ptr的函数,所以-我不明白…对象构造的明确性是由构造函数定义的。因此,在返回对象时不能隐式地这样做,但在其他情况下可以显式地这样做。是的<代码>从UNIQUIGYPTR 从裸指针定义的构造函数定义为显式。这不是IMO的原因。<代码> GETHYIT 返回唯一指针,很明显,返回指针从转移所有权的方式。好点,但我认为C++不够聪明,无法区分这个案例和问题中的情况。所以,两者都是允许的,或者两者都是禁止的。@einpoklum:这确实是原因。如果这是一个愚蠢的问题,请原谅我,但为什么不只是
使_独一无二?@erip:因为这是一个MWE。事实上,我们有
auto p=do\u stuff\u,它返回一个原始指针()
对,但是你可以简单地做
auto get\u it(){auto p=new int;return std::make_unique(p);}
,不是吗?我认为转发比直接呼叫更可取。呃。。。不。构建和转发对象是有区别的。另外,为什么你把自己称为OP?:)通常,自我回答应该添加一些其他答案没有的内容。我认为@Stas的答案涵盖了您的答案。感谢您将Sutter先生的建议和EWG的讨论提请我注意,这非常有启发性(并且
return std::unique_ptr<int>(p);
auto get_it() {
    auto p = new int;
    return std::unique_ptr<int>(p);
}