unique_ptr C ++ 03仿真中的move函数

时间:2011-12-09 18:55:51

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

我正在尝试了解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)); 
    }
    
  3. 在上面的代码中,显式转换为T似乎没什么必要。实际上,如果没有明确转换为T,Visual Studio 2010会非常高兴。

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

1 个答案:

答案 0 :(得分:3)

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

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

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