2012-07-20 122 views
17

假设我有以下代码:移动与向量::的push_back

#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)); 
} 

我知道的std ::向量的元素被连续存储,不像一个std ::名单。在上面的代码a2被移动,但真的没有a2复制到矢量vava.push_back(a2);和有何区别?

+2

在你的情况下,'std :: move'ing'a2'确实是* nothing *,因为它是一个平面类型(即它没有外部数据)并且仍然会复制。 – Xeo 2012-07-20 03:59:26

+0

@cdhowie谢谢。纠正。 – ggg 2012-07-20 04:01:55

+0

您可能想阅读[可以请某人解释移动语义给我?](http://stackoverflow.com/questions/3106110/)的移动语义介绍。 – fredoverflow 2012-07-20 07:45:53

回答

26

就你而言,没有有效的区别,因为你使用的是编译器提供的拷贝构造函数。使用可移动构建的对象时,您会看到明显的性能差异,并需要花费大量的精力进行复制。在这种情况下,使用push_back(x)将创建该对象的副本,而push_back(move(x))会告知push_back()它可能“窃取”x的内容,使x处于不可用和未定义状态。

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

+1

为什么?移动C-tor会自动生成,不是这样吗? – ForEveR 2012-07-20 04:09:30

+6

@ForEveR无论是否自动生成都没关系,因为在可以移动的'A'结构中没有分配。你只有两个'int's,移动构造函数将执行与复制构造函数相同的操作:将源对象上的ints中存储的值分配给新对象。在这种类型的移动场景中不可能进行优化,因为它已经尽可能优化了。 – cdhowie 2012-07-20 04:11:08

+0

@cdhowie所以在移动过程中总会有东西被复制? – ggg 2012-07-20 04:39:02

14

当您使用va.push_back(a2)版本vector<T>::push_back(const T&)将被调用,当您使用va.push_back(move(a2))版本vector<T>::push_back(T&&)将被称作......

但在你的情况下,有对性能比较没有什么区别,因为

15隐式定义的复制/移动构造函数,用于非工会类 X对其基础和成员执行成员复制/移动。

段落12.8 n3337草稿。

0

我想说明一些其他答案没有结束的事情;是?.push_back(move(?))会比你的情况下慢(?.push_back(?)),因为移动构造函数需要零\设置移动的对象,这有效地写了\复制两个对象。

+0

移动构造函数不需要对移动的对象执行任何操作。除非移动了需要重置为空的指针,否则它不需要任何东西。 (编译器生成的移动构造函数不会覆盖源对象。) – cdhowie 2017-09-12 13:54:51