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

相关推荐
rhythm-ring25 分钟前
宏定义续行符 \ 的使用与踩坑
c语言·c++
XZ-0700011 小时前
week2-1-可视化
开发语言·python
Java后端的Ai之路1 小时前
14、Python - 责任链模式
服务器·开发语言·人工智能·python·责任链模式
吴声子夜歌1 小时前
Java——基本类型
java·开发语言
江安下小雨1 小时前
muduo网络库(十六):新增连接池模块
网络·c++
「QT(C++)开发工程师」1 小时前
C++11 std::unique_ptr — 独占所有权的智能指针
c语言·开发语言·c++·qt
不正经学生2 小时前
C语言动态内存管理(上):堆上的自由与责任
c语言·开发语言·c++·算法·面试
AI情绪识别开源2 小时前
检信AI高一分班分科智选评估系统 v2.0测试报告
开发语言·数据结构·人工智能·科技
纯.Pure_Jin(g)2 小时前
靶场PHP函数整理+防御方式
开发语言·php·ctf
zl.rs2 小时前
配置更适合生产环境的coredump
c++