std :: move是否可以与左值引用一起使用? std :: move如何在标准容器上工作?

std :: move是否可以与左值引用一起使用? std :: move如何在标准容器上工作?

问题描述:

#include <vector>

struct A { int a[100]; };

void foo (const A& a) {
  std::vector<A> vA; 
  vA.push_back(std::move(a));  // how does move really happen?
}

int main () {
  A a;
  foo(a);
}

上面的代码编译良好.现在到处都有记载,move避免了复制.
以下是我的查询:

The above code compiles fine. Now everywhere it's written that move avoids copying.
Following are my queries:

  1. move在处理左值时是否真的起作用? [non]-const参考?
  2. 即使使用右值引用",当对象出现时如何避免复制 插入上面的标准容器中?
  1. Does the move really work when one deals with a lvalue [non]-const reference?
  2. Even with "rvalue reference", how is the copy avoided when the object is inserted into a standard container like above?

例如

void foo (A&& a) {  // suppose we invoke this version
  std::vector<A> vA; 
  vA.push_back(std::move(a));  // how copy is avoided?
}

std::move不执行任何操作.它实际上将左值引用转换为右值引用.在这种情况下,移动的结果是const A &&(顺便说一句,这完全没用).

std::move doesn't do a move. It actually casts the lvalue reference to an rvalue reference. In this case, the result of the move is a const A && (which is totally useless by the way).

std::vector对于const A &A &&具有重载,因此将选择const A &的重载,并且const A &&隐式转换为const A &

std::vector has an overload for a const A & and a A &&, so the overload with const A & will get chosen and the const A && is implicitly casted to const A &

可以在const对象上调用std::move的事实对于大多数程序员来说都是奇怪的/意想不到的行为,尽管它在某种程度上是允许的. (很可能他们有一个用例,或者没有一个用例可以阻止它)

The fact that std::move can be called on const objects, is strange/unexpected behavior for most programmers, though it somehow is allowed. (Most likely they had a use case of it, or none to prevent it)

更具体地针对您的示例,将调用类A的move构造函数.由于A是POD,因此很可能只需要进行复制,因为所有位都只需要移动/复制到A的新实例.

More specific for your example, the move constructor of the class A will get called. As A is a POD, this most likely will just do a copy as all bits just have to move/copied to the new instance of A.

由于标准仅指定原始对象必须处于有效(尽管未指定)状态,因此您的编译器可以将位保留在A中,而不必将它们全部重置为0.实际上,大多数编译器将保留这些位就位,因为更改它们需要额外的指令,这对性能不利.

As the standard only specifies that the original object has to be in a valid though unspecified state, your compiler can keep the bits in A in place and doesn't have to reset them all to 0. Actually, most compilers will keep these bits in place, as changing them requires extra instructions, which is bad for performance.