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

相关推荐
aramae4 小时前
模拟实现strcmp()(C语言)
c语言·开发语言·后端
泡海椒5 小时前
PDF 表格样式优化:jquick-pdf 边框、圆角、背景色
java·开发语言·pdf
Beyond_System|系统之外5 小时前
【学编程】Python基础编程题100道(21-60)
开发语言·python·算法
景熙55236 小时前
15.Java 8 Stream 流入门到实战
java·开发语言·数据结构
汉克老师7 小时前
GESP2026年9月认证C++六级( 第三部分编程题(1、数组划分))精讲
c++·gesp·小学生·学c++编程
千里码aicood7 小时前
基于PLC与机器视觉的智能分拣控制系统设计
c++·自动化·plc
漂流瓶jz7 小时前
UVA-1442 洞穴 题解答案代码 算法竞赛入门经典第二版
c++·算法·题解·aoapc·算法竞赛入门经典·uva
朽棘不雕7 小时前
进一步了解模板
c++
Bruce_Liuxiaowei8 小时前
Python 实例赋值遮蔽类属性:一个从不报错的静默陷阱
开发语言·python·语法糖
aramae10 小时前
MySQL内置函数(7)
开发语言·笔记·后端·mysql·其他