【问题标题】: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 可以很容易地按值传递。

标签: c++ c++11 unique-ptr explicit-constructor


【解决方案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(?)}

【讨论】:

    猜你喜欢
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 2015-07-23
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    • 2011-05-17
    • 2015-04-15
    相关资源
    最近更新 更多