含数组成员的结构体赋值聚合初始化报错:GCC版本差异原因探究
GCC版本间聚合赋值兼容性问题解析
这段代码在GCC 8.5至10.5版本中使用g++ -std=c++17编译会失败,但在GCC 11.1及以上版本用相同编译选项可正常运行;若将结构体中的数组成员替换为非数组类型(如int),所有8.5至11版本的GCC都能正常编译。这是编译器bug还是C++标准后续修正的问题?
测试代码
struct T { char arr[2]; }; int main() { T data; data = { "V" }; return 0; }
低版本GCC报错信息
<source>: In function 'int main()': <source>:6:18: error: no match for 'operator=' (operand types are 'T' and '<brace-enclosed initializer list>') data = { "V" }; ^ <source>:1:8: note: candidate: constexpr T& T::operator=(const T&) struct T { char arr[2]; }; ^ <source>:1:8: note: no known conversion for argument 1 from '<brace-enclosed initializer list>' to 'const T&' <source>:1:8: note: candidate: constexpr T& T::operator=(T&&) <source>:1:8: note: no known conversion for argument 1 from '<brace-enclosed initializer list>' to 'T&&' Compiler returned: 1
问题解析
这是GCC修复的编译器bug,而非C++标准的后续修正。
C++17标准明确允许聚合类型使用花括号初始化列表直接赋值:本质是先通过列表初始化构造一个临时的聚合对象,再调用默认生成的拷贝或移动赋值运算符完成赋值。对于包含char arr[2]的结构体T,{ "V" }完全符合初始化要求——字符串字面量"V"包含字符'V'和终止符'\0',刚好能填满长度为2的字符数组。
GCC 8.5到10.5版本存在实现缺陷,没有正确处理包含数组成员的聚合类型的列表初始化转换,导致编译器无法识别{ "V" }可以构造临时T对象,进而匹配不到对应的赋值运算符。而GCC 11.1修复了这个bug,正确处理了这类场景的隐式转换,因此编译通过。
当把数组成员替换为非数组类型时,低版本GCC能正常处理列表初始化到聚合类型的转换,这也侧面验证了问题根源在于数组类型成员的初始化逻辑实现错误。
内容的提问来源于stack exchange,提问作者ABu
相关产品推荐
相关产品推荐

