738 字
4 分钟
std::vector::emplace_back 用法详解
std::vector::emplace_back 用法详解
概述
在容器末尾就地构造元素,直接将参数传递给元素的构造函数,避免多余的临时对象创建与拷贝/移动操作。
基本用法
头文件:<vector>
template< class... Args >void emplace_back( Args&&... args ); // (C++11)args: 可变模板参数,完全透传给元素构造函数。- 与
push_back的核心区别:push_back会先在调用处根据传入的参数生成一个临时对象,再通过移动或拷贝构造存入容器。而emplace_back利用完美转发(Perfect Forwarding),直接在vector的预分配内存处原址(in-place)构造对象,理论上开销更小。
进阶用法与多角度运用
1. 结构体与类的按参数透传
最典型的用法是结合具有对应参数数量与类型的结构体构造函数:
struct Student { std::string name; int ch, math, eng, total;
// 构造函数(有了它 emplace_back 更方便) Student(const std::string& n, int c, int m, int e, int t) : name(n), ch(c), math(m), eng(e), total(t) {}};
std::vector<Student> stu;// 直接按序传入构造函数的 5 个参数stu.emplace_back("Bob", 90, 90, 90, 270);2. C++17 聚合初始化的支持
如果在结构体中未显式定义构造函数,它属于聚合体(Aggregate)。在 C++17 之前,emplace_back 不能直接用于聚合体的按成员初始化。但从 C++17 开始,emplace_back 支持对聚合体的直接列表初始化:
struct Point { double x, y, z;};
std::vector<Point> pts;// C++17 之前需要提供构造函数,C++17 起支持pts.emplace_back(1.0, 2.0, 3.0);示例
#include <iostream>#include <vector>#include <string>
int main() { std::vector<std::pair<int, int>> points;
// 方法一:push_back // 会调用 pair 的构造函数生成临时对象,然后移动到 points 尾部 points.push_back({3, 4});
// 方法二:emplace_back // 直接传入 pair 所需的两个参数,就地构造 points.emplace_back(3, 4);
std::cout << points.back().first << "," << points.back().second;}常见问题
- 重载歧义与非预期显式转换
emplace_back的直接构造特性,可能会无意中调用带有explicit关键字的构造函数,导致意想不到的后果:
std::vector<std::vector<int>> vv;// 错误:无意间调用了 vector<int>(size_t count),创建了包含 10 个 0 的内层 vectorvv.emplace_back(10);
// 正确:使用 push_back 或明确类型来防止歧义,意图是放入一个包含 10 的 vectorvv.push_back(std::vector<int>{10});- 初始化列表(花括号)的不兼容性
由于
emplace_back的参数包推导机制,它无法像push_back({x, y})那样直接接受花括号初始化列表。如果结构体需要大括号进行隐式推导,必须显式给出类型或改用push_back。
struct Point { double x, y; };std::vector<Point> pts;
// 错误:emplace_back 不支持大括号列表初始化pts.emplace_back({1.0, 2.0});
// 正确:pts.push_back({1.0, 2.0});// 或在 C++17 下:pts.emplace_back(1.0, 2.0);复杂度
均摊常数复杂度:O(1)。仅当超出 capacity 时发生内存重分配,会导致线性开销 O(N)。
关联知识点
std::vector::push_back:接受对象实例作为参数。std::vector::emplace:在迭代器指定的位置进行就地构造。
赞助支持
如果这篇文章对你有帮助,欢迎赞助支持!
std::vector::emplace_back 用法详解
https://whywood.cn/posts/2026-4-20/emplace_back/ 最后更新于 2026-04-21