可能重复:
当向量增长时如何强制执行移动语义?
insert
,push_back
和emplace
( _back
) 可能导致重新分配 a std::vector
。我很困惑地看到以下代码在重新分配容器时复制元素而不是移动它们。
#include <iostream>
#include <vector>
struct foo {
int value;
explicit foo(int value) : value(value) {
std::cout << "foo(" << value << ")\n";
}
foo(foo const& other) noexcept : value(other.value) {
std::cout << "foo(foo(" << value << "))\n";
}
foo(foo&& other) noexcept : value(std::move(other.value)) {
other.value = -1;
std::cout << "foo(move(foo(" << value << "))\n";
}
~foo() {
if (value != -1)
std::cout << "~foo(" << value << ")\n";
}
};
int main() {
std::vector<foo> foos;
foos.emplace_back(1);
foos.emplace_back(2);
}
在我使用特定编译器(GCC 4.7)的特定机器上,这将打印以下内容:
foo(1)
foo(2)
foo(foo(1))
~foo(1)
~foo(1)
~foo(2)
但是,当删除复制构造函数 ( foo(foo const&) = delete;
) 时,会生成以下(预期的)输出:
foo(1)
foo(2)
foo(move(foo(1))
~foo(1)
~foo(2)
这是为什么?移动通常不会比复制更有效率,或者至少不会低很多吗?
值得注意的是,GCC 4.5.1 做了预期的事情——这是 GCC 4.7 中的回归还是一些巧妙的优化,因为编译器认为我的对象复制起来很便宜(但是如何复制?!)?
另请注意,我确保这是由重新分配引起的,通过实验将 afoos.reserve(2);
放在插入之前;这不会导致执行复制或移动。