为什么双空花括号{{}}用一个元素创建一个std :: initializer_list <double>,而不是零?

时间:2016-01-10 16:02:11

标签: c++ initializer-list

我有以下构造函数:

MyItem(std::initializer_list<double> l) {
    std::cout << "l size " << l.size() << ")" << std::endl;
}

以后用双花括号调用:

MyItem{{}}

l.size()给出的结果是1。

这种行为背后的机制是什么?

似乎嵌套{}扮演的是唯一元素的默认构造函数,但我不太明白为什么以及类型推导如何在这里工作。

2 个答案:

答案 0 :(得分:10)

当您使用大括号(列表初始化)初始化MyItem对象时,您显示的列表构造函数非常贪婪。

这些会传递一个空列表:

MyItem foo({});
MyItem foo{std::initializer_list<double>{}};

这会传递一个包含单个元素的列表 - 值初始化double(0.0):

MyItem foo{{}};

这是有效的,因为在某些情况下,您可以简单地使用大括号代替已知类型。在这里,它更喜欢列表构造函数,给定列表应包含double

为了完整性,这看起来像是传递了一个空列表,但如果它有一个默认构造函数,它实际上会初始化foo(或者在特殊情况下,它会做几乎相同的事情)。如果没有默认构造函数,它将选择列表构造函数as shown here

MyItem foo{};

答案 1 :(得分:5)

此表达式

MyItem{{}}

表示显式类型转换(功能表示法)。

根据C ++标准(5.2.3显式类型转换(功能表示法))

  
      
  1. 类似地,一个simple-type-specifier或typename-specifier后跟一个   braced-init-list创建指定类型的临时对象   direct-list-initialized(8.5.4)与指定的braced-init-list,   它的值是临时对象作为prvalue。
  2.   

类MyItem具有转换初始化列表构造函数

MyItem(std::initializer_list<double> l) {
    std::cout << "l size " << l.size() << ")" << std::endl;
}
为显式类型转换选择的

。实际上它等同于调用

MyItem( {{}} );

因此构造函数获取带有一个元素的初始化列表

{ {} }

可以使用空括号{}初始化double类型的标量对象。

结果表达式创建了一个MyItem类型的临时对象,该对象由初始化列表初始化,该列表包含一个double类型的元素,该元素通过空括号进行值初始化。