来自 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&lt;T&gt;); 并通过int i = 42; foo(&amp;i); 调用它 在 C++14 中你可以return std::make_unique&lt;some_type&gt;(data); return std::make_unique&lt;some_type&gt;(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&lt;foo&gt;(?) 而不是new foo(?)

【讨论】:

以上是关于来自 T* 的 std::unique_ptr<T> 的构造函数显式背后的原因是啥?的主要内容,如果未能解决你的问题,请参考以下文章

调整 std::vector<std::unique_ptr<T>> 大小的性能

boost::ptr_vector 与 std::vector<std::unique_ptr<T>>? [关闭]

在 class<std::unique_ptr<B>> 中强制模板函数为 T=B*

std::unique_ptr的用法

智能指针unique_ptr记录

std::unique_ptr::reset 重载问题