为什么<initializer_list>使用自动必须包括在内?

Why must <initializer_list> be included for using auto?

本文关键字:包括 initializer lt list 为什么 gt      更新时间:2023-10-16

SO上已经有一个类似的问题,但我想强调大括号初始化列表的另一个方面。请考虑以下事项:

auto x = {1}; //(1)

这是格式不正确的 (8.5.4/2(,除非包含标头<initializer_list>。但是为什么?该标准说,模板std::initializer_list不是预定义的。这是否意味着声明 (1( 引入了一种新的类型?在所有其他可能使用auto的情况下,例如

auto y = expr;

如果expr是表达式,则自动推断的类型已存在。另一方面,从逻辑的角度来看,编译器必须为构造{1}分配一个隐式类型,然后std::initializer_list是另一个名称。但是在声明 (1( 中,我们不想命名此类型。那么为什么必须包含此标头。nullptr也有类似的情况。它的类型隐式存在,但要显式命名它,您必须包含<cstddef>

这是不一样的。std::nullptr_tstd::initializer_list的规则实际上是不同的。

std::nullptr_t只是内置类型的 typedef。它的定义是

namespace std {
  using nullptr_t = decltype(nullptr);
}

无论是否包含标头,该类型都存在。

std::initializer_list是类模板,而不是预定义类型。除非包含定义它的标头,否则它实际上不存在。特别是,初始值设定项列表{ 1 }没有类型 std::initializer_list<int> ;它根本没有类型,因为它不是一个表达式。(初始值设定项列表是特殊的语法构造,不能出现在表达式可以出现的所有位置。

std::initializer_list只是有点特别。首先,对于如何从初始值设定项列表语法初始化std::initializer_list有特殊规则(分配数组并让对象引用它(。但是,这首先需要定义std::initializer_list

第二种特殊情况是auto型扣除。这里还有一个特殊的规则。但同样,这并不意味着编译器会自动定义类型;这只是意味着它会识别它。