在下面的代码中,我希望永远不会调用A
的复制构造函数,因为项目应该直接在带有emplace_back
的向量上创建,然后总结果应该返回 - 值优化。
情况似乎如此。但是,每次我附加到向量时,所有先前的项目都会被emplace_back
调用复制。为什么会这样?
#include <iostream>
#include <vector>
#include <string>
using namespace std;
static int _id = 0;
class A{
public:
A(): name(_id++){
cout << "Created" << this->name << endl;
}
A(const A& other): name(other.name){
cout << "Copied" << this->name << endl;
}
A(const A&& other): name(other.name){
cout << "Moved" << this->name << endl;
}
~A(){
cout << "Deleted"<< this->name <<endl;
}
private:
int name;
};
vector<A> f2(){
cout << "Entering f2" << endl;
auto ret = vector<A>();
for (int i = 0; i < 3; i++){
//auto obj = A();
cout << "Adding obj" << endl;
ret.emplace_back();
cout << "Added obj" << endl;
}
cout << "Returning" << endl;
return ret;
}
int main()
{
{
auto c = f2();
cout << "Exiting stack" << endl;
}
return 0;
}
我用gcc 4.8.4使用以下任何一个编译它:
gcc main.cpp -std=c++11
gcc main.cpp -std=c++11 -O3
输出结果为:
Entering f2
Adding obj
Created0
Added obj
Adding obj
Created1
Copied0
Deleted0
Added obj
Adding obj
Created2
Copied0
Copied1
Deleted0
Deleted1
Added obj
Returning
Exiting stack
Deleted0
Deleted1
Deleted2
我希望没有副本,例如:
Entering f2
Adding obj
Created0
Added obj
Adding obj
Created1
Added obj
Adding obj
Created2
Added obj
Returning
Exiting stack
Deleted0
Deleted1
Deleted2
使用emplace_back
更改push_back
并不能解决这个问题,并增加了额外的动作。
答案 0 :(得分:4)
Vector会在存储空间不足时重新分配内存块,并将旧对象复制到新位置。您可以通过致电vector.reserve(<expected number of items>);
来大幅减少此类重新分配的次数
另外值得注意的是,向量保证了摊销常数push_back
的复杂性。这意味着当您不断添加项目时,重新分配的次数会越来越少,因此通常不会引起关注。
或者,如果您只需要某种容器并且不需要将其连续分配到内存中,请考虑使用其他容器。与std::deque
一样。
答案 1 :(得分:3)
另外,如果你标记你的移动构造函数noexcept,那么当向量增长时,它将移动而不是复制。