C++ emplace_back嵌套对象优化及多参数构造调用疑问
emplace_back构造多参数内部对象的问题 我来帮你理清楚这个问题的根源,以及对应的解决办法:
首先,我们先回顾一下emplace_back的工作原理:它会把你传入的参数完美转发给容器元素的构造函数,也就是这里的outterObject的构造函数。你的outterObject只有一个构造函数:outterObject(innerObject member);,所以emplace_back需要接收一个能用来构造outterObject的参数——也就是一个innerObject对象(或者能隐式转换为它的类型)。
当innerObject只有单参数构造时,传入5可以隐式转换为innerObject,所以没问题;但当innerObject需要两个int构造时,编译器没办法自动把(5,5)或者{5,5}推导为innerObject的构造参数(尤其是初始化列表{5,5}没法被完美转发的模板参数推导识别),所以调用失败。
下面是几种可行的解决方式:
方法1:显式构造innerObject传入
直接在emplace_back里显式创建innerObject对象,这样编译器就明确知道要把它传给outterObject的构造函数:
v1.emplace_back(innerObject(5, 5)); // 或者用列表初始化的方式 v1.emplace_back(innerObject{5, 5});
方法2:给outterObject添加适配构造函数
如果你不想每次都显式构造innerObject,可以给outterObject新增一个接受两个int的构造函数,内部直接初始化member成员:
struct innerObject { innerObject(int, int); }; class outterObject { innerObject member; public: outterObject(innerObject member) : member(std::move(member)) {} // 新增适配构造函数 outterObject(int a, int b) : member(a, b) {} }; int main() { std::vector<outterObject> v1; v1.emplace_back(5, 5); // 现在可以直接调用了 }
这种方式更简洁,让emplace_back直接把两个int转发给outterObject的新构造函数,内部完成innerObject的初始化。
方法3:使用模板构造函数转发参数(进阶)
如果你的innerObject构造参数更多,或者想保持outterObject的构造函数简洁,还可以给outterObject添加一个模板构造函数,转发任意参数给innerObject的构造:
class outterObject { innerObject member; public: outterObject(innerObject member) : member(std::move(member)) {} // 模板构造函数,转发任意参数给innerObject的构造 template<typename... Args> outterObject(Args&&... args) : member(std::forward<Args>(args)...) {} };
这样不管innerObject需要多少个构造参数,你都可以直接通过emplace_back传入:
v1.emplace_back(5, 5); // 如果innerObject有三参数构造,也可以直接传 // v1.emplace_back(1, 2, 3);
内容的提问来源于stack exchange,提问作者Newbie

