C++使用emplace_back向vector插入C类对象传参报错如何解决
错误根因
std::vector::emplace_back 是变长模板函数,依赖模板实参推导匹配传入参数和目标类型构造函数的参数列表。不带类型标识的花括号初始化列表{std::make_shared<A>(), 2}没有明确类型,无法被模板推导,因此第一种写法直接编译失败。
你给出的第二种写法显式构造了临时B对象,不符合emplace_back原地构造的设计目标,且注意你当前定义的C构造函数第一个参数为std::vector<B>,这种写法也会因为参数类型不匹配编译失败。
解法(分两种场景匹配你的实际需求)
场景1:C的构造函数定义正确,第一个参数为std::vector<B>
你需要先构造符合要求的std::vector<B>,再传递给C的构造函数,全程无多余开销的写法如下:
std::vector<C> vecC; // 先原地构造vector<B>,再移动给C的构造函数,vector的移动操作无额外内存拷贝开销 std::vector<B> tmp_vec; tmp_vec.reserve(1); tmp_vec.emplace_back(std::make_shared<A>(), 2); vecC.emplace_back(std::move(tmp_vec), false);
如果可以接受极少量的B对象移动开销,也可以简化写法:
vecC.emplace_back(std::initializer_list<B>{{std::make_shared<A>(), 2}}, false);
场景2:C的构造函数为笔误,第一个参数实际为B
这种场景下可以通过新增完美转发构造函数实现完全原地构造,无任何临时对象生成:
// 修改C的定义,新增完美转发构造 struct C { // 原有构造保留,新增以下构造函数 template<typename... Args, typename = std::enable_if_t<std::is_constructible_v<B, Args...>>> C(Args&&... b_args, bool c): v_(std::forward<Args>(b_args)...), c_(c) {} B v_; bool c_; }; // 调用代码,直接传递B的构造参数即可 std::vector<C> vecC; vecC.emplace_back(std::make_shared<A>(), 2, false);
如果不想修改C的定义,显式构造B临时对象的写法实际开销极低,因为B的移动构造是轻量化的,绝大多数场景下性能完全符合要求。
内容的提问来源于stack exchange,提问作者Irbis
相关产品推荐
相关产品推荐

