以下是示例代码:
using namespace std;
struct A {
A(unique_ptr<int> s)
: _s(move(s)){}
unique_ptr<int> _s;
};
int main(int argc, const char * argv[]) {
auto&& ptr = make_unique<int>(5);
A a{ptr}; // Error
A b{move(ptr)}; // OK
return 0;
}
我的第一个猜测是,它应该可以在不使用&#39; move&#39;的情况下工作,但我会调用隐式删除的复制构造函数&#39;在clang上。也许是&#39; ptr&#39;是不是左值(奇怪的是?)?有人可以澄清一下吗?
答案 0 :(得分:5)
这里有几件事情,其中大部分涉及价值类别分类中各部分的标准的措辞。但这是它的要点:
ptr
类型的扣除将遵循转发引用的规则。是的,它将是unique_ptr<int>&&
。但ptr
不是左值。这是理解的棘手问题。它是一个你已经绑定到rvalue的引用,当然,但现在该对象不再是未命名的,也不是对它的引用。
现在它是一个带名字的对象。直觉上,因为你可以分配它,它是一个左值(在一般意义上)。因此,它不会自己绑定到右值引用。所以你最终试图调用复制构造函数。
要移动它,您需要再次将其转换为过期值(从类型系统的角度来看)。这就是std::move
通过返回一个(未命名的)右值引用来做的事情。
答案 1 :(得分:1)
传递一个r值:
A a{ make_unique<int>(5) };
或std ::移动l值
auto ptr = make_unique<int>(5);
A b{ move(ptr) };