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。

相关推荐
揽星河..27 分钟前
【C++】类和对象
c++·算法
D e re k ZH1 小时前
C++ 并发、未定义行为与工程化难点(No 3)
数据结构·c++·算法·面试
不积跬步无以至千里mmbb261 小时前
rust_analysis
开发语言·后端·rust
暴力求解2 小时前
C++ ---继承(二)
开发语言·c++·算法
陈飞EXCEL2 小时前
北京杰飞 IT 旗下妙码生花少儿Python编程上线两大学习系统
开发语言·python·学习
代龙涛3 小时前
WordPress Query 查询机制详解(WP_Query)
开发语言·后端·php·wordpress
znsoft3 小时前
MaClaw(码卡龙)技术拆解:一个 Go + React 的可自进化智能体平台
开发语言·react.js·golang
凉茶钱4 小时前
红黑树:用“颜色”换“平衡”,set 与 map 的底层发动机
开发语言·c++·红黑树
高冷小鱼殿下5 小时前
内部类Lambda与枚举
java·开发语言
shelly聊外贸5 小时前
WhatsApp 聊天记录如何导出为 CSV?使用 Python 进行数据分析
开发语言·python·数据分析