【问题标题】:The move function in unique_ptr C++03 emulationunique_ptr C++03 仿真中的 move 函数
【发布时间】:2011-12-09 18:55:51
【问题描述】:

我试图了解C++03 emulation of unique_ptr 是如何实现的。 unique_ptr 很像 std::auto_ptr 但更安全。在 auto_ptr 隐式转移所有权(即静默)的情况下,它会吐出编译器错误。例如,一个简单的分配。函数move 是模拟 unique_ptr 安全性的关键。

问题:

  1. 为什么会有三个移动函数?
  2. 接受引用并将其转换为右值的第三个移动函数实现(简化)如下。

    T move(T &t) { 
      return T(detail_unique_ptr::rv<T>(t)); 
    }
    

在上面的代码中,对 T 的显式转换似乎是不必要的。事实上,Visual Studio 2010 在没有显式转换为 T 的情况下非常满意。

T move(T &t) {
  return detail_unique_ptr::rv<T>(t);
}

g++、clang、Comeau,然而,不喜欢第二个版本。这些编译器抱怨unique_ptr&lt;T&gt; 没有将detail_unique_ptr::rv&lt;T&gt; 作为参数的构造函数。这是为什么? unique_ptr 已经定义了一个将detail_unique_ptr::rv&lt;T&gt; 作为参数的(非显式)构造函数。为什么那个不是自动拾取的?

【问题讨论】:

标签: c++ move-semantics unique-ptr c++03


【解决方案1】:

原因是因为你不能用另一个 unique_ptr 初始化一个 unique_ptr 进行用户定义的转换(到 rv,通过将右值传递给 unique_ptr 的 rv 构造函数)。但是,当没有显式调用 unique_ptr 的 ctor 时(如在 unique_ptr(...) 中),您会进行复制初始化,在您的情况下首先成功构造一个右值临时 unique_ptr 但随后无法将该临时复制到返回值目标对象中,因为在该副本中,不允许用户定义的转换(这也称为原则规则“在初始化中没有两个用户定义的转换”)。 Msvc 允许副本使用带有非常量 unique_ptr 引用的 ctor,这是非标准的。

当从同一个类的对象复制一个类的初始化时,没有这样的两步初始化。源对象只是传递给unique_ptr的非显式构造函数,它将使用rv-take构造函数将其转换为rv,并通过这种方式成功构造返回值目标对象。

出于同样的原因,没有从unique_ptr&lt;Derived&gt;unique_ptr&lt;Base&gt; 的隐式转换。在第一步中,unique_ptr&lt;Base&gt; 将成功创建,但是当将该临时对象复制到 unique_ptr&lt;Base&gt; 目标对象时,不能使用用户定义的转换的限制会阻止成功。

【讨论】:

  • 感谢 litb!你想告诉我为什么需要另外两个移动函数吗?
  • 为什么不直接调用unique_ptr&lt;T&gt;(detail_unique_ptr::rv&lt;T&gt;)进行不需要自定义转换的复制呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-15
  • 1970-01-01
  • 1970-01-01
  • 2014-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多