5

关于 SO已经有一个类似的问题,但我想强调braced-init-lists 的另一个方面。考虑以下:

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

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

auto y = expr;

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

4

1 回答 1

8

那不一样。std::nullptr_t和的规则std::initializer_list实际上是不同的。

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

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

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

std::initializer_list是类模板,而不是预定义的类型。除非您包含定义它的标头,否则它实际上不存在。特别是,初始化列表{ 1 }没有 type std::initializer_list<int>;它根本没有类型,因为它不是表达式。(初始化列表是特殊的句法结构,不能出现在表达式可以出现的任何地方。)

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

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

于 2013-06-14T10:04:05.443 回答