为何列表初始化std::initializer_list失败?嵌套初始化是否合法?
关于std::initializer_list初始化的问题解答
一、列表初始化报错,直接初始化合法的原因
先看报错的代码示例:
int main(void) { std::initializer_list<int> lst1{}; std::initializer_list<int> lst2{lst1}; // error }
GCC给出的错误信息:
error: could not convert '{lst1}' from '
' to 'std::initializer_list '
而直接初始化的代码可以正常编译:
std::initializer_list<int> lst2(lst1); // OK
核心原因在于C++标准对std::initializer_list的列表初始化有特殊优先级规则:
- 当使用列表初始化(花括号语法)构造
std::initializer_list<T>对象时,编译器会优先尝试将花括号内的元素转换为T类型,以此生成一个元素序列来初始化目标initializer_list。这里T是int,而lst1是std::initializer_list<int>类型,无法隐式转换为int,因此编译失败。 - 当使用直接初始化(圆括号语法)时,编译器会调用
std::initializer_list的拷贝构造函数——该类型的拷贝操作是标准允许的,因此可以正常编译。
对应的C++标准规则:根据[dcl.init.list]章节的规定,初始化std::initializer_list<T>类型对象时,列表初始化的处理逻辑是将花括号中的每个元素隐式转换为T,再构建对应的initializer_list。这个过程会优先匹配元素到T的转换,而不会考虑initializer_list自身的拷贝构造函数。
二、嵌套initializer_list的列表初始化合法性
以下代码是合法的:
int main(void) { std::initializer_list<int> lst1{}; std::initializer_list<std::initializer_list<int>> lst2{lst1}; //OK }
原因是此时lst2的元素类型T是std::initializer_list<int>,花括号内的lst1正好是该类型,完全符合列表初始化的要求:编译器会将lst1作为单个元素,构造出包含该元素的std::initializer_list<std::initializer_list<int>>,因此可以正常编译。
内容的提问来源于stack exchange,提问作者mada
相关产品推荐
相关产品推荐

