为何使用列表初始化的对象在GCC9编译通过,GCC5.1却失败?
GCC5.1与GCC9编译差异原因分析
代码示例
struct AAA { int xxx = 1; }; int main() { AAA p; new AAA{p}; }
GCC5.1编译错误信息
/home/genstor/cpp/test.cpp:11:18: error: cannot convert 'AAA' to 'int' in initialization new AAA{p}; ^
原因分析
C++标准的规则变化
C11中,聚合类型的定义明确要求不能包含带有类内初始化的非静态成员;但C14放宽了这一限制,允许聚合类型包含带有类内默认初始化的非静态成员。GCC版本的实现差异
- GCC5.1对C++14标准的这一规则实现存在缺陷:它没有正确将带有
int xxx = 1;的AAA识别为聚合类型。当执行new AAA{p};时,编译器错误地将其解析为用AAA对象p去初始化结构体的单个成员xxx(int类型),因此抛出“无法将AAA转换为int”的错误。 - GCC9则正确实现了C++14的规则:它会将
AAA判定为聚合类型,AAA{p}属于合法的聚合拷贝初始化,编译器会用对象p来初始化新的AAA实例,等同于调用拷贝构造函数,因此编译通过。
- GCC5.1对C++14标准的这一规则实现存在缺陷:它没有正确将带有
与GCC4.8问题的关联
GCC4.8.1的问题是符合C11标准的:在C11中带类内成员初始化的结构体不属于聚合类型,当时的列表初始化规则对这类类型的支持有限;而GCC5.1的问题是标准更新后的实现bug,和前者属于不同阶段的问题——前者是遵循旧标准的正常限制,后者是新标准落地时的实现缺陷。
编译命令:g++ ~/cpp/test.cpp --std=c++14
内容的提问来源于stack exchange,提问作者mathworker
相关产品推荐
相关产品推荐

