std :: move是否适用于左值引用?std :: move如何在标准容器上运行?

iam*_*ind 6 c++ reference move language-lawyer c++11

#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);
}
Run Code Online (Sandbox Code Playgroud)

上面的代码编译得很好.现在到处写的都move避免了复制.
以下是我的疑问:

  1. 请问move-当一个人用左值[无]涉及真正的工作const参考?
  2. 即使使用"右值参考",当对象插入上面的标准容器时,如何避免复制?

例如

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

JVA*_*pen 9

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

std::vector有一个a const A &和a A &&的重载,所以const A &将选择重载并const A &&隐式转换为const A &

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

更具体的例子,A​​类的移动构造函数将被调用.由于A是POD,这很可能只会复制,因为所有位只需要移动/复制到A的新实例.

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

  • 当你在C++中考虑将`std :: move`添加到一些否则会导致副本的代码中时,它就不再是奇怪的了.一般来说,Movable概念意味着"如果可能的话移动,否则复制".它们并不意味着"如果可能则移动,否则无法编译". (4认同)