为什么指针在返回时不能自动转换为 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
获得了指针的所有权,你肯定不想 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
}
因为转换或强制转换需要适当的强制转换运算符(在源类型上)或构造函数(在目标类型上)。在这种情况下,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_ptr
的 constructor 被声明为 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。
让我通过一个例子来提出我的问题。
#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
获得了指针的所有权,你肯定不想 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
}
因为转换或强制转换需要适当的强制转换运算符(在源类型上)或构造函数(在目标类型上)。在这种情况下,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
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_ptr
的 constructor 被声明为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。