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(,)提出的两个版本的关于使
明确化的提案,以及两个“回复”,他们辩称不这样做:Howard Hinnant和Ville Voutilainen以及Filip Roséen。经过几次讨论和民意调查,这一问题最终以全国广告部的名义解决了——这不是一个缺陷return
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);
}