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
参考?
- 即使使用"rvalue reference",当对象时如何避免复制
像上面一样插入标准容器中?
例如
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 对象上调用,这是大多数程序员的 strange/unexpected 行为,尽管它在某种程度上是允许的。 (很可能他们有它的用例,或者 none 来阻止它)
对于您的示例更具体,class A 的移动构造函数将被调用。由于 A 是一个 POD,这很可能只是复制,因为所有位只需要 move/copied 到 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"
}
#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
参考?- 即使使用"rvalue reference",当对象时如何避免复制 像上面一样插入标准容器中?
例如
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 对象上调用,这是大多数程序员的 strange/unexpected 行为,尽管它在某种程度上是允许的。 (很可能他们有它的用例,或者 none 来阻止它)
对于您的示例更具体,class A 的移动构造函数将被调用。由于 A 是一个 POD,这很可能只是复制,因为所有位只需要 move/copied 到 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"
}