一、核心区别
| 对比项 | 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。