假设我有以下课程:
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
的移动构造函数?我猜第一个它会被移动两次,但第二个它只会被移动一次?
答案 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)
会说明所提供的参数集没有匹配函数。