You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 08:48:16