如何在C++构造函数初始化列表中通过返回pair的函数初始化成员?
构造无默认构造成员的可行方案
现有无法修改的类A、B,以及返回std::pair<A,B>的自由函数func,代码如下:
#include <utility> struct A { A() = delete; explicit A(int) {} }; struct B { B() = delete; explicit B(char) {} }; std::pair<A, B> func() // 替换为tuple时问题相同 { return { A{42}, B{'F'} }; }
需要在Foo类的构造函数中初始化A类型成员a和B类型成员b,但三种常规尝试均失败:
尝试1:初始化列表中使用结构化绑定
编译报错:expected identifier before '[' token,结构化绑定语法无法直接用于初始化列表。
class Foo { A a; B b; public: Foo() : [a, b] { func() } // error: expected identifier before '[' token // 替换为{func()}、= func()或(func))均无法解决 { } };
尝试2:用std::tie替代结构化绑定
编译报错:expected class-name before '(' token at column 21,std::tie无法作为初始化列表的成员初始化器使用。
class Foo { A a; B b; public: Foo() : std::tie(a, b) = func() } // error: expected class-name before '(' token at column 21 { } };
尝试3:构造函数体内赋值
编译报错:use of deleted functions 'A::A()' and 'B:B()',因为A、B无默认构造函数,成员会在进入构造函数体前尝试默认初始化,导致错误。
class Foo { A a; B b; public: Foo() { const auto& p{func()}; a = p.first; b = p.second; } };
可行解决方案
方案1:委托构造函数(推荐)
通过私有委托构造函数接收func()返回的std::pair,一次性初始化a和b,仅调用一次func,无额外开销:
class Foo { A a; B b; // 私有构造函数,接收pair并移动初始化成员 Foo(std::pair<A, B> p) : a(std::move(p.first)), b(std::move(p.second)) {} public: // 委托给私有构造函数,传入func()的结果 Foo() : Foo(func()) {} };
方案2:C++17 lambda初始化器(无副作用场景适用)
如果func()调用无副作用(比如不会修改全局状态、重复调用结果一致),可以用lambda表达式在初始化列表中直接提取func()的返回值成员:
class Foo { A a; B b; public: Foo() : a([](){ return std::move(func().first); }()), b([](){ return std::move(func().second); }()) {} };
注意:此方案会调用两次func(),仅当func()无副作用时使用。
内容的提问来源于stack exchange,提问作者Happy Green Kid Naps
相关产品推荐
相关产品推荐

