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

为何该C++代码在std=c++17编译通过,std=c++20编译失败?

C++20聚合初始化报错:要么全用指定初始化,要么全不用的原因及解决方法

错误原因

你的代码在C17编译通过但C20失败,是因为C++20对聚合初始化的指定初始化器规则做了严格收紧:

当对一个聚合体进行初始化时,如果使用了任意一个指定初始化器(即.成员名=值的形式),那么该聚合体的所有直接初始化子句必须全部是指定初始化器,不允许混合位置式初始化(按顺序对应成员/基类)和指定初始化。

看你的代码:

B foo {{.a = 1, .b = false}, .c = 7};

B是继承自A的聚合体,它的初始化有两个直接子句:

  • 第一个子句{.a = 1, .b = false}是位置式初始化:按顺序对应B的第一个“成员”(基类A),没有用指定初始化器标记这个基类的初始化;
  • 第二个子句.c = 7是指定初始化器,直接指定了成员c。

这种混合写法刚好违反了C++20的新规则,因此编译报错。

解决方法

有两种合规的写法可选:

方法1:全部使用指定初始化器

C++20允许用基类名{...}的形式指定初始化基类,写法如下:

struct A {
    int a;
    bool b;
};

struct B : A {
    long c;
};

int main(void) {
    B foo {.A{.a = 1, .b = false}, .c = 7};
}

方法2:全部使用位置式初始化

按聚合体的成员顺序(基类在前,成员在后)依次初始化:

struct A {
    int a;
    bool b;
};

struct B : A {
    long c;
};

int main(void) {
    B foo {{1, false}, 7};
}

补充说明

C17没有这个限制,允许在聚合初始化中混合位置式和指定式的写法,这也是你的代码在C17能编译通过的原因。C++20新增该规则是为了消除初始化时的歧义,让聚合初始化的行为更明确、一致。

内容的提问来源于stack exchange,提问作者Palace Chan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 04:28:16