使用vector :: push_back移动

ggg*_*ggg 33 c++ c++11

假设我有以下代码:

#include <vector>
struct A {
    int a;
    int x;
};
int main() {
    using namespace std;
    A a1;
    A a2;
    vector<A> va;
    va.push_back(a1);
    va.push_back(move(a2));
}
Run Code Online (Sandbox Code Playgroud)

我知道std :: vector的元素是连续存储的,与std :: list不同.在上面的代码a2被移动但是真的没有复制a2到向量vava.push_back(a2);和之间有什么区别va.push_back(move(a2));

cdh*_*wie 42

在您的情况下,没有有效的区别,因为您使用的是编译器提供的复制构造函数.当使用可移动构造的对象时,您会看到明显的性能差异,并且需要花费很多精力来复制.在这种情况下,使用push_back(x)会创建对象的副本,同时push_back(move(x))会告诉push_back()它可能"窃取"内容x,留x在不可用和未定义的状态.

考虑一下你是否有一个list(std::vector<std::list<int> >)向量,你想推送一个包含100,000个元素的列表.如果没有move(),将复制整个列表结构和所有100,000个元素.随着move(),一些指针和其他一小部分数据被混乱,这就是它.这将更快,并且将需要更少的总体内存消耗.

  • @ForEveR是否自动生成一个并不重要,因为`A`结构中没有可以移动的分配.你只有两个`int`s,移动构造函数将执行复制构造函数将执行的操作:将源对象上的int中存储的值分配给新对象.在这种类型的移动场景中不可能进行优化,因为它已经达到最佳状态. (8认同)
  • @ggg:"移动"并不是某种神奇的药剂,你会把你的代码倒在一起,让事情不会发生."移动"的作用是允许您在复制操作需要分配新内存等时指定所有权的转移.如果你的副本不会做那样的话,那么移动并没有多大帮助. (8认同)
  • 为什么?move c-tor 会自动生成,不是吗? (2认同)

For*_*veR 17

当你使用va.push_back(a2)版本时vector<T>::push_back(const T&)会调用,当你使用va.push_back(move(a2))版本时vector<T>::push_back(T&&)会被调用...

但是在你的情况下,性能没有差别,因为

15非联合类X的隐式定义的复制/移动构造函数执行其基础和成员的成员复制/移动.

第12.8段3337年草案.