【发布时间】:2012-10-19 18:49:08
【问题描述】:
假设我有一个(平凡的)类,它可以移动构造和移动分配,但不能复制构造或复制分配:
class movable
{
public:
explicit movable(int) {}
movable(movable&&) {}
movable& operator=(movable&&) { return *this; }
movable(const movable&) = delete;
movable& operator=(const movable&) = delete;
};
这很好用:
movable m1(movable(17));
这当然行不通,因为m1 不是右值:
movable m2(m1);
但是,我可以将 m1 包装在 std::move 中,这会将其转换为右值引用,以使其工作:
movable m2(std::move(m1));
到目前为止,一切都很好。现在,假设我有一个(同样微不足道的)容器类,它包含一个值:
template <typename T>
class container
{
public:
explicit container(T&& value) : value_(value) {}
private:
T value_;
};
但是,这不起作用:
container<movable> c(movable(17));
编译器(我尝试过 clang 4.0 和 g++ 4.7.2)抱怨我试图在 container 的初始化列表中使用 movable 的已删除复制构造函数。同样,将 value 包裹在 std::move 中使其工作:
explicit container(T&& value) : value_(std::move(value)) {}
但是为什么在这种情况下需要std::move? value 不是已经属于 movable&& 类型了吗? value_(value) 与 movable m1(movable(42)) 有何不同?
【问题讨论】:
-
一个标准参考有望遵循,但并非所有 && 变量的使用都应该是破坏性的 - 你可以想象一个演员在丢弃它之前使用它的 && 参数采取了十几步。所以当你用 && 变量构造另一个对象时,你仍然需要说这个特殊用途是允许移动的……
-
T&&类型的命名值是左值,而相同类型的未命名值是右值。 -
在我的手机上,所以不会接听,但命名的临时是左值。这里,
value是一个左值表达式。 -
@Yakk:不需要标准参考。这是一个合适的答案。
标签: c++ c++11 rvalue-reference move-semantics move-constructor