在SO上已经有类似的question,但我想强调 braced-init-lists 的另一个方面。请考虑以下事项:
auto x = {1}; //(1)
除非包含标题<initializer_list>
,否则这是不正确的(8.5.4 / 2)。但为什么?标准说,模板std::initializer_list
未预定义。这是否意味着,声明(1)引入了一种新类型?在所有其他情况下,可以使用auto
,例如
auto y = expr;
其中expr
是表达式,自动推断类型已存在。另一方面,从逻辑的角度来看,编译器必须为构造{1}
分配 implicite type ,其中std::initializer_list
是另一个名称。但是在声明(1)中我们不想命名这种类型。那么为什么必须包括这个标题。 nullptr
也存在类似的情况。其类型隐含存在,但要明确指出它,您必须包含<cstddef>
。
答案 0 :(得分:8)
那不一样。 std::nullptr_t
和std::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
类型扣除。这里也有一个特殊的规则。但同样,这并不意味着编译器会自动定义类型;它只是意味着它会识别它。