738 字
4 分钟

std::vector::emplace_back 用法详解

2026-04-21
浏览量 加载中...

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;
}

常见问题#

  1. 重载歧义与非预期显式转换 emplace_back 的直接构造特性,可能会无意中调用带有 explicit 关键字的构造函数,导致意想不到的后果:
std::vector<std::vector<int>> vv;
// 错误:无意间调用了 vector<int>(size_t count),创建了包含 10 个 0 的内层 vector
vv.emplace_back(10);
// 正确:使用 push_back 或明确类型来防止歧义,意图是放入一个包含 10 的 vector
vv.push_back(std::vector<int>{10});
  1. 初始化列表(花括号)的不兼容性 由于 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
许可协议
CC BY-NC-SA 4.0
最后更新于 2026-04-21

评论区

目录