来自 T* 的 std::unique_ptr<T> 的构造函数显式背后的原因是啥?
Posted
技术标签:
【中文标题】来自 T* 的 std::unique_ptr<T> 的构造函数显式背后的原因是啥?【英文标题】:What's the reasoning behind std::unique_ptr<T>'s constructor from T* being explicit?来自 T* 的 std::unique_ptr<T> 的构造函数显式背后的原因是什么? 【发布时间】:2015-11-23 01:18:55 【问题描述】:由于std::unique_ptr
提供了一种方便的方法来避免内存泄漏并确保异常安全,因此传递它们而不是原始指针是明智的。因此,一个人可能想要(成员)具有类似签名的函数
std::unique_ptr<some_type> foo(some data);
不幸的是,在实现这样的功能时,不能简单地实现
std::unique_ptr<some_type> foo(some data)
return new some_type(data) ; // error
但必须改为
std::unique_ptr<some_type> foo(some data)
return std::move( std::unique_ptr<some_type>( new some_type(data) ) ); // awkward
因为构造函数unique_ptr::unique_ptr(pointer)
是explicit
。这个构造函数是 explicit
背后的原因是什么?
创建构造函数explicit
的一个动机是防止意外的隐式类型转换。但是,由于unique_ptr
不能按值传递,这应该不是问题,不是吗?
【问题讨论】:
您可以拥有一个void foo(unique_ptr<T>);
并通过int i = 42; foo(&i);
调用它
在 C++14 中你可以return std::make_unique<some_type>(data);
return std::make_unique<some_type>(data);
。不幸的是,make_unique
在 c++11 中被“遗忘”了,但 c++14 修复了这个问题。在c++11中也可以write your ownmake_unique
。
而且您不需要在 C++11 中显式地 std::move
临时。
你抽什么烟? unique_ptr 可以很容易地按值传递。
【参考方案1】:
unique_ptr
获得传递指针的所有权。获得所有权应该是明确的——你不希望某些指向“神奇地”的指针被某个类拥有(和删除)(这是不推荐使用的std::auto_ptr
的问题之一)。
例如:
void fun(std::unique_ptr<X> a) ....
X x;
fun(&x); // BOOM, deleting object on stack, fortunately it does not compile
fun(std::unique_ptr<X>(&x)); // compiles, but it's explicit and error is clearly visible
请注意,return
语句中不需要 std::move
(特殊语言异常 - 作为 return
参数的局部变量可被视为“已移动”)。
另外 - 在 C++14 中,您可以使用 std::make_unique
来减少尴尬:
return std::make_unique<some_data>(some_data_argument1, arg2);
(它也可以很容易地添加到 C++11 - 阅读here)
【讨论】:
只是想指出std::make_unique
在 C++14 之前的一些编译器中可用,MSVC12 就是一个例子。【参考方案2】:
采用唯一 ptr 的参数不应默默地获得指针的所有权。
因此 ctor 是显式的。
要返回,请尝试make_unique<foo>(?)
而不是new foo(?)
。
【讨论】:
以上是关于来自 T* 的 std::unique_ptr<T> 的构造函数显式背后的原因是啥?的主要内容,如果未能解决你的问题,请参考以下文章
调整 std::vector<std::unique_ptr<T>> 大小的性能
boost::ptr_vector 与 std::vector<std::unique_ptr<T>>? [关闭]