std::move对左值引用起作用吗?std::move如何在标准容器上工作

Does std::move work with lvalue references? How does std::move work on standard containers?

本文关键字:std move 标准 工作 引用 起作用      更新时间:2023-10-16
#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避免复制。
以下是我的查询:

  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?
}

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

std::vectorconst A &A &&有重载,因此const A &的重载将被选择,const A &&被隐式强制转换为const A &

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

对于您的示例更具体,类A的move构造函数将被调用。由于A是一个POD,这很可能只是做一个复制,因为所有的位只需要移动/复制到A的新实例中。

由于标准只指定原始对象必须处于有效但未指定的状态,因此编译器可以将a中的位保留在适当的位置,而不必将它们全部重置为0。实际上,大多数编译器会保留这些位,因为更改它们需要额外的指令,这对性能不利。

创建一个代码片段来显示它。虽然在您的示例中将调用默认构造函数,但您可以理解。

#include <vector>
#include <iostream>
struct A { 
  int a[100];
  A() {}
  A(const A& other) {
    std::cout << "copy" << std::endl;
  }
  A(A&& other) {
    std::cout << "move" << std::endl;
  }
};
void foo(const A& a) {
  std::vector<A> vA; 
  vA.push_back(std::move(a));
}
void bar(A&& a) {
  std::vector<A> vA; 
  vA.push_back(std::move(a));
}
int main () {
  A a;
  foo(a);            // "copy"
  bar(std::move(a)); // "move"
}