emplace_back无法支持<brace-enclosed initializer list>吗?
问题
vector
使用emplace_back()
无法添加元素,使用push_back()
却可以。
难道emplace_back()
与列表初始化不兼容?非也!
复现
代码片段
std::vector<std::array<int, 4> > vec;
vec.emplace_back({1,2,3,4}); // error
vec.push_back({1,2,3,4}); // pass
报错信息
<source>:8:31: error: no matching function for call to 'std::vector<std::array<int, 4> >::emplace_back(<brace-enclosed initializer list>)'
8 | vec.emplace_back({1,2,3,4});
| ^
include/c++/11/bits/stl_vector.h:1212:2: note: candidate template ignored: substitution failure: deduced incomplete pack <(no value)> for template parameter '_Args'
emplace_back(_Args&&... __args);
^
深究
分析std::vector
的成员函数:
文档指出emplace_back()
本质上是一个模板函数,具体形式为
template< class... Args >
void emplace_back( Args&&... args );
对于简单的结构我们一般省略模板参数让编译器自行推导。对于复杂类型,
模板意味若不确定传入args
类型,编译器无法推导缺省模板参数Args
的值,
进而无法使用std::forward<Args>(args)...
转发参数进行构造。
说的好,但还是没有解释为什么push_back()
可以调用?
从实现上push_back()
并非模板函数,且其实现存在拷贝而非直接构造
void push_back( const T& value );
编译器将隐式调用std::array::operator=()
处理传入的参数完成类型转换。
解决
只需将上述代码改为:
vec.emplace_back<std::array<int, 4>>({1,2,3,4});
// or
vec.emplace_back(std::array<int, 4>{{1, 2, 3, 4}});
即可通过编译!
参考
std::vector<T,Allocator>::emplace_back - cppreference.com
std::vector<T,Allocator>::push_back - cppreference.com
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理