std::move对左值引用起作用吗?std::move如何在标准容器上工作
Does std::move work with lvalue references? How does std::move work on standard containers?
#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
避免复制。
以下是我的查询:
- 当一个人处理左值时,
move
真的有效吗[非]-const
参考? - 即使使用"右值引用",当对象是否像上面那样插入标准容器?
。
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::vector
对const 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"
}
相关文章:
- Usages of std::move
- 在C++中对T*类型执行std::move的意外行为
- 关于std::move的使用,是否有编译警告
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 通过实例理解std::move及其目的
- 返回一个带有 std::move 的对象并链接函数
- 当 std::move 与 C 样式数组或不移动对象时会发生什么
- std::move a const std::vector in a lambda capture
- "std::forward"和"std::move"真的不生成代码吗?
- 如何在没有 std::move 的情况下移动临时对象
- 关于在成员重载中使用 std::move() 的问题
- 显式清除 std::move 之后的源资源
- std::move 如何使原始变量的值无效?
- 复制elision、std::move和链式函数调用
- 如果真的需要std::move,我们应该什么时候声明右值refs
- 使用std::move将std::unique_ptr作为qt信号参数传递
- 无法使用带有 std::move 的自定义删除器插入 std::unique_ptr
- C++:我应该在 return 语句中显式使用 std::move() 来强制移动吗?
- 编译器是否足够聪明,以至于 std::move 变量超出范围?
- std::move() 或其在局部变量上的显式等价物可以允许 elision 吗?