You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中std::vector两种对象添加方式的差异及效率对比

问题解答:std::vector::push_back直接构造对象 vs 预先创建对象再添加的效率差异

好问题!咱们结合C++的版本特性和对象构造细节,来拆解这两种写法的效率差异:

先看两种实现的代码

方式一:push_back临时构造的对象

struct foo { 
    int val; 
    std::string str; 
    foo(int _val, std::string _str) : val(_val), str(_str) {} 
};
int main() { 
    std::vector<foo> list; 
    std::string str("hi"); 
    int val = 2; 
    list.push_back(foo(val,str)); 
    return 0; 
}

方式二:先创建对象再push_back

int main() { 
    std::vector<foo> list; 
    std::string str("hi"); 
    int val = 2; 
    foo f(val,str); 
    list.push_back(f); 
    return 0; 
}

效率差异分析

1. C++11之前的情况

在没有移动语义的年代,两种方式都会触发一次拷贝构造:

  • 方式一:先构造临时foo对象,再把这个临时对象拷贝到vector的内存中,最后临时对象被销毁。
  • 方式二:先在栈上构造foo f,再把f拷贝到vector的内存中,f会在main函数结束时才销毁。

此时两者的拷贝次数完全一致,效率差异几乎可以忽略——唯一的区别是临时对象的销毁时机,但这对性能影响极小,选哪种更多是代码风格问题。

2. C++11及之后的情况

C++11引入了右值引用和移动语义,这时候两种方式的差异就变得明显了:

  • 方式一中的foo(val, str)是临时对象(右值),push_back会调用foo的移动构造函数(如果没有自定义移动构造,编译器会生成默认版本)。对于std::string这种带堆内存资源的成员来说,移动操作只是转移内存指针,不需要复制字符串内容,效率比拷贝高很多。
  • 方式二中的f是左值,push_back会调用拷贝构造函数,需要完整复制str的内容到vector的新对象中,开销更大。

3. 极致优化:emplace_back

如果追求最高效率,更推荐使用std::vector::emplace_back,它可以直接在vector的内存空间中构造foo对象,完全避免拷贝或移动操作:

list.emplace_back(val, str); // 直接在vector的内存里构造foo,一步到位

总结

  • 在C++11及之后的版本中,方式一(直接push_back临时对象)比方式二更高效,核心是利用移动语义减少了资源拷贝的开销。
  • 如果你的代码适配C++11及以上,优先选方式一,或者更优的emplace_back;
  • 在C++11之前,两者效率差异可以忽略,按自己习惯的风格写就行。

内容的提问来源于stack exchange,提问作者pattymills

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:09:39