C++ emplace_back 与 push_back 详解

一、核心区别

对比项 push_back emplace_back
参数 接受一个已存在的对象 接受构造函数的参数
过程 先构造对象,再拷贝到容器 直接在容器中构造对象
效率 可能产生临时对象和拷贝 零拷贝,最高效

一句话总结push_back是"插入对象",emplace_back是"就地构造"。


二、代码示例对比

2.1 基础演示
复制代码
cpp

#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Student {
public:
    string name;
    int age;
    
    Student(string n, int a) : name(n), age(a) {
        cout << "构造: " << name << endl;
    }
    
    Student(const Student& other) : name(other.name), age(other.age) {
        cout << "拷贝构造: " << name << endl;
    }
};

int main() {
    vector<Student> students;
    
    // push_back:先构造临时对象,再拷贝到容器
    cout << "=== push_back ===" << endl;
    students.push_back(Student("Alice", 20));
    // 输出:构造: Alice
    // 输出:拷贝构造: Alice
    
    // emplace_back:直接在容器中构造,无拷贝
    cout << "\n=== emplace_back ===" << endl;
    students.emplace_back("Bob", 22);
    // 输出:构造: Bob
    
    return 0;
}
2.2 实际应用场景
复制代码
cpp

#include <vector>
#include <string>
#include <map>
using namespace std;

int main() {
    // 场景1:添加简单类型
    vector<int> nums;
    nums.push_back(10);      // OK
    nums.emplace_back(20);   // 也可以
    
    // 场景2:构造pair(推荐emplace_back)
    vector<pair<string, int>> pairs;
    pairs.emplace_back("key", 42);     // 直接传参,高效
    pairs.push_back({"key", 42});      // 需要花括号构造临时对象
    
    // 场景3:复杂对象(emplace_back优势明显)
    vector<map<string, vector<int>>> complexVec;
    complexVec.emplace_back();   // 构造空map
    // complexVec.push_back({}); // 也行,但会多一次拷贝
    
    // 场景4:不可拷贝类型(只能用emplace_back)
    vector<unique_ptr<int>> ptrs;
    ptrs.emplace_back(new int(42));  // OK
    // ptrs.push_back(new int(42));  // 错误!unique_ptr不可拷贝
    
    return 0;
}

三、使用建议

3.1 优先使用 emplace_back 的场景
cpp 复制代码
cpp

// 1. 需要临时构造对象(最常见)
vector<string> strs;
strs.emplace_back("hello");  // 推荐
strs.push_back("hello");     // 会产生临时对象

// 2. 多参数构造
struct Point { int x, y; };
vector<Point> points;
points.emplace_back(3, 4);   // 直接传两个参数
points.push_back({3, 4});    // 需要花括号

// 3. 复杂类型构造
vector<vector<int>> matrix;
matrix.emplace_back(5, 10);  // 构造包含10个5的vector
matrix.push_back({5, 10});   // 构造包含5和10的vector(含义不同!)
3.2 使用 push_back 的场景
cpp 复制代码
cpp

// 1. 添加已存在的对象(语义更清晰)
string existing = "world";
vec.push_back(existing);     // 明确是拷贝
vec.emplace_back(existing);  // 也能工作,但push_back更直观

// 2. 使用移动语义时
vec.push_back(std::move(existing));  // 明确表示移动
vec.emplace_back(std::move(existing)); // 也可以

四、总结

使用场景 推荐方法 原因
临时构造新对象 emplace_back 避免临时对象,效率更高
添加已存在的对象 push_back 语义清晰,代码可读性好
多参数构造 emplace_back 代码更简洁
不可拷贝类型 emplace_back 必须使用

最佳实践 :在大多数情况下,优先使用 emplace_back ,它更通用且高效。只有在明确需要表达"插入一个已存在的对象"时,才使用 push_back

相关推荐
漂流瓶jz1 小时前
UVA-12174 Shuffle的播放记录 题解答案代码 算法竞赛入门经典第二版
数据结构·c++·算法·图论·滑动窗口·算法竞赛入门经典·uva
Darkwanderor2 小时前
线程概念和Linux线程
linux·c语言·c++
clear sky .2 小时前
[freertos源码阅读]task.c任务篇
c语言·开发语言
lingran__2 小时前
C++ 高阶数据结构:红黑树万字详解|完整原理推导 + 插入实现 + 完整性校验【STL 底层】
数据结构·c++·面试·红黑树·二叉搜索树·平衡二叉树·stl底层
XR1234567882 小时前
工业园区整体组网,方案对比怎么选?
开发语言·php
东东最爱敲键盘2 小时前
day9.C++多态之虚函数
开发语言·c++
码云数智-园园2 小时前
类似小鹅通的知识付费小程序平台有哪些
开发语言
Darkwanderor2 小时前
Linux线程控制
linux·c语言·c++
snow@li2 小时前
Java:跨平台原理与JDK、JRE、JVM全景深度解析
java·开发语言·jvm