【发布时间】:2015-08-20 03:28:35
【问题描述】:
据我了解,当向量增加容量时,它会分配新内存,将所有内容复制(移动?)到新数组,然后销毁旧数组:
vector<int> v;
v.emplace_back(1);
v.emplace_back(2); cout<<&v[0]<<endl; // outputs 0x4b16d0
v.emplace_back(3); cout<<&v[0]<<endl; // outputs 0x4b16f0
+-----+
0x4b16d0 | 1 2 |
+-----+
+---------+
0x4b16f0 | 1 2 3 |
+---------+
在上面的例子中,1 和 2 move 如何从 0x4b16d0 到 0x4b16f0?
用用户定义的类更新
struct foo {
foo() {}
foo(const foo &) { cout << "copy\n"; }
foo(foo &&) noexcept { cout << "move\n"; }
};
int main() {
vector<foo> v;
cout<<"1st emplace_back() \n"; v.emplace_back(); cout<<" addr of 1st element: "<<&v[0]<<endl;
cout<<"2nd emplace_back() \n"; v.emplace_back(); cout<<" addr of 1st element: "<<&v[0]<<endl;
}
$ g++ -std=c++11 -g a.cpp; ./a.exe
1st emplace_back()
addr of 1st element: 0x6f16d1
2nd emplace_back()
move
addr of 1st element: 0x6f16f1
我的问题是,即使调用了move ctor,它仍然会将数据从一个地方复制到另一个地方,对吗?
如果是这样,这是否意味着当向量使用移动语义增加其容量时它根本不会提高性能?
【问题讨论】:
-
它使用您问题中描述的方法。它会复制它们。
-
具有用户定义的移动构造器 + 调试器 + 断点 + 视图调用堆栈的非平凡类可能会让您了解您的实现如何做到这一点。还是您的问题是专门针对
int的? -
@Deqing 你知道这两个都应该使用
&v[0],对吧? -
提示:每次调用
v.emplace_back()后输出v.capacity()。现在,你为什么认为第一个元素的地址在改变? -
可能还需要记住:如果对象具有无抛出移动构造函数,向量只会移动您的对象。默认情况下,它最终会以这种方式声明(很可能)。如果移动构造函数可能抛出,那么向量将使用复制构造函数。它基于这个标准实用程序:en.cppreference.com/w/cpp/utility/move_if_noexcept
标签: c++ c++11 vector move-semantics