传递为右值参考vs双移值

时间:2018-02-14 06:11:03

标签: c++ c++11 move-semantics

假设我有以下课程:

class foo {  
    std::unique_ptr<blah> ptr;
}

这两者之间的区别是什么:

foo::foo(unique_ptr p) 
   : ptr(std::move(p))
{ }

foo::foo(unique_ptr&& p)
   : ptr(std::move(p)
{ }

当被称为

auto p = make_unique<blah>();
foo f(std::move(p));

两者都编译,我猜两个都必须使用unique_ptr的移动构造函数?我猜第一个它会被移动两次,但第二个它只会被移动一次?

2 个答案:

答案 0 :(得分:0)

std::unique_ptr是一个不可复制的类,这意味着你要么传递一个常量引用(只读访问),要么移动它(rvalue)来表达/给予所有权。

第二种情况(获取显式rvalue)是正确的实现,因为您的意图是传递所有权并且std::unique_ptr已删除了副本分配/构造函数。

在第一种情况下,禁止复制并且arg是rvalue(在传递之前移动了它),因此编译器使用移动构造函数。然后所有权属于新参数,并再次将其移动到内部字段再次传递所有权,而不是一个非常好的解决方案。 (请注意,此声明不是限制性的,它允许任何值类型。如果std::unique_ptr可以复制,则会在此处使用复制构造函数,隐藏实际问题。)

就结果代码而言,std::move是对rvalue的简单转换,因此两者都是相同的。在正确性方面,必须使用第二个。

答案 1 :(得分:0)

他们做同样的事情,即将指针移动两次(转换为2次转换)。 唯一的实际区别是,如果您按值std::unique_ptr传递代码,代码就会中断。

编译器foo::foo(unique_ptr p)会抱怨复制构造函数被删除。

拥有foo::foo(unique_ptr&& p)会说明所提供的参数集没有匹配函数。