你如何将左值转换为右值?而且`new`左值会发生什么?

时间:2013-05-19 17:35:17

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

我想使用std::vector将对象移动到std::vector::push_back()。这似乎是可能的,因为有一个std::vector::push_back(value_type&& val)函数。但是由于std::vector::push_back(value_type const & val)的存在,它复制并且将成为重写的调用,我需要将左值对象转换为右值。

这是怎么做到的?

示例:

struct X { int x; X(int x) : x(x) {} };

int main()
{
    std::vector<X> ax;
    X x(3);
    ax.push_back(x);  // <= Want to move x in to vector ax, not copy.
    return 0;
}

实际上,也许它不可能?我问这个是因为在写完这个例子后,我的新问题是:

  • 如果我将x移至axx.x的价值是多少?如果X有明确的析构函数,那么x在离开范围时会发生什么?

1 个答案:

答案 0 :(得分:4)

只需使用std::move()

ax.push_back(std::move(x));

关于你的问题:

  

如果我将x移动到ax,x.x的值是多少?

在这种情况下,您的类X不包含显式声明的移动构造函数,因此编译器将生成一个成员移动X的成员。由于X只有一个int类型的成员,并且移动int与复制它没有什么不同,因此x.x将具有与移动之前相同的值

  

如果X有一个显式的析构函数,x在离开作用域时会发生什么?

如果X具有用户声明的析构函数,则会禁止生成隐式移动构造函数 - 但不会生成隐式复制构造函数。因此,这个函数调用:

ax.push_back(std::move(x));

会导致x复制ax。在任何情况下,x都会在超出范围时被销毁,因为它具有自动存储持续时间 - 无论用户声明的析构函数是否存在。

一般情况下,不应该对已经移动的对象的状态做出假设,除了该状态是有效的(C ++ 11标准的第17.6.5.15/1段保证了这种情况)标准库的类型)。

具体来说,这意味着唯一能够安全地处理已移动对象的函数是那些对该对象的状态没有任何先决条件的函数。通常,两个这样的函数是析构函数和(复制或移动)赋值运算符。