push_back & emplace_back
push_back & emplace_back
内容
在C++中,vector<vector<int>>
使用push_back
和emplace_back
时对初始化列表的处理差异源于两者参数传递机制的不同。以下是详细解释:
1. push_back
的工作原理
-
隐式类型转换:
push_back
的参数类型是明确的const vector<int>&
或vector<int>&&
。当传递{1, 2, 3}
时,编译器会自动将其隐式转换为一个临时的vector<int>
对象(调用vector<int>
的构造函数接受std::initializer_list<int>
)。 -
代码示例:
std::vector<std::vector<int>> v; v.push_back({1, 2, 3}); // 等效于 v.push_back(std::vector<int>{1, 2, 3});
2. emplace_back
的限制
-
直接构造参数:
emplace_back
的参数是直接传递给元素构造函数的一组参数。然而,初始化列表{1, 2, 3}
的类型是std::initializer_list<int>
,而vector<int>
的构造函数需要显式接受这个类型。 -
模板参数推导失败:
由于模板参数推导规则的限制,编译器无法将{1, 2, 3}
推导为std::initializer_list<int>
。因此,必须显式指明参数类型。 -
正确写法:
v.emplace_back(std::initializer_list<int>{1, 2, 3}); // 显式传递初始化列表 // 或直接构造临时对象 v.emplace_back(std::vector<int>{1, 2, 3});
3. 根本原因
方法 | 参数类型 | 初始化列表处理 |
---|---|---|
push_back |
const vector<int>& 或 vector<int>&& |
接受隐式转换,允许从{...} 构造临时vector<int> |
emplace_back |
模板参数包(需匹配vector<int> 的构造函数) |
无法推导{...} 为std::initializer_list<int> |
4. 解决方法
(1) 显式传递std::initializer_list<int>
v.emplace_back(std::initializer_list<int>{1, 2, 3});
(2) 使用直接构造临时对象
v.emplace_back(std::vector<int>{1, 2, 3});
(3) 使用C++17的类模板参数推导(CTAD)
在C++17及以上版本中,可以简化构造:
v.emplace_back(std::vector{1, 2, 3}); // 无需指定<int>
5. 性能对比
方法 | 内存操作 | 效率 |
---|---|---|
push_back |
构造临时vector<int> → 移动或拷贝到容器 |
可能有一次拷贝/移动 |
emplace_back |
直接在容器内存中构造vector<int> |
无临时对象开销 |
6. 总结
-
push_back
的便捷性:
依赖隐式转换,适合快速插入已知类型的对象。 -
emplace_back
的灵活性:
需显式传递构造参数,避免临时对象,但需注意模板参数推导的限制。
通过理解两者底层机制,可以更高效地选择适合场景的方法。
本文作者:Gold_stein
本文链接:https://www.cnblogs.com/smartljy/p/18748609
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步