1.42、vector中的push_back()和emplace_back()的区别

机制区别

  • • push_back
    先构造一个临时对象(通常通过拷贝或移动构造函数),然后将该对象拷贝或移动到容器内部。
    例如:v.push_back(T(args));会先创建临时T对象,再移动或拷贝进vector
  • • emplace_back
    直接在容器尾部内存位置原地构造对象,通过完美转发传递构造函数参数,避免了临时对象的创建和移动。
    例如:v.emplace_back(args);直接调用T的构造函数在容器内构造。

性能影响

  • • emplace_back通常减少一次额外的构造或移动操作,在构造复杂对象时更高效。
  • • push_back在已有对象(尤其是右值或临时对象)时,性能差异不明显,因为移动构造可以高效转移资源。
  • • 编译器优化可能缩小两者差距,但emplace_back的设计目标是避免不必要的临时对象。

使用场景建议

场景 推荐使用 说明
已有一个完整对象,需要将其加入容器 push_back 直接传入对象或右值,语义清晰且安全
需要直接传递构造参数,在容器内原地构造 emplace_back 避免临时对象,提升性能,适合复杂对象或非拷贝构造类型
对象构造函数是显式(explicit emplace_back push_back无法隐式调用显式构造函数,emplace_back可直接转发参数
代码可读性和维护性优先 push_back(默认) 语义简单,编译器对模板推导负担更小,调试更友好

示例

struct Widget {
    Widget(int x, double y);
    // ...
};

std::vector<Widget> v;

// 使用push_back,需要先构造临时对象
v.push_back(Widget(423.14));  // 先构造临时Widget,再移动到vector

// 使用emplace_back,直接在vector尾部构造
v.emplace_back(423.14);       // 直接调用Widget(int, double)构造函数,无临时对象

总结

  • • emplace_back的优势在于避免临时对象的构造和移动,适合直接传递构造参数原地构造新元素。
  • • push_back适合已有对象的插入,语义更明确且更安全。
  • • 在大多数日常场景中,push_back足够且易于理解;当性能敏感或需要直接构造复杂对象时,优先考虑emplace_back
    本文首发于【讳疾忌医-note】公众号,未经授权,不得转载。
    (加入我的知识星球,免费获取账号,解锁所有文章。)

 

阅读剩余
THE END