9

在 C++11 中,初始化 a 似乎是合法的std::map<std::string, int>,如下所示:

std::map<std::string, int> myMap = {
     { "One",   1 },
     { "Two",   2 },
     { "Three", 3 }
};

直观地说,这是有道理的——大括号括起来的初始值设定项是字符串对的列表,并且std::map<std::string, int>::value_typestd::pair<std::string, int>(可能有一些条件const

但是,我不确定我是否理解打字在这里的工作原理。如果我们去掉这里的变量声明并且只使用大括号括起来的初始化器,编译器就不会知道它正在查看 a,std::initializer_list<std::pair<std::string, int>>因为它不知道大括号对表示std::pairs。因此,似乎编译器以某种方式推迟了将类型分配给大括号封闭的初始值设定项的行为,直到它从std::map构造函数中获得足够的类型信息以实现嵌套大括号用于对。我不记得在 C++03 中发生过这样的事情;据我所知,表达式的类型从不依赖于它的上下文。

哪些语言规则允许此代码正确编译并允许编译器确定用于初始化列表的类型?我希望得到具体参考 C++11 规范的答案,因为这真的很有趣!

谢谢!

4

2 回答 2

9

在表达式中

std::map<std::string, int> myMap = {
     { "One",   1 },
     { "Two",   2 },
     { "Three", 3 }
};

在右侧,您有一个花括号初始化列表,其中每个元素也是一个花括号初始化列表。发生的第一件事std::map是考虑初始化列表构造函数。

map(initializer_list<value_type>,
    const Compare& = Compare(),
    const Allocator& = Allocator());

map<K, V>::value_typepair<const K, V>在这种情况下,是 的 typedef pair<const string, int>。内部花括号初始化列表可以成功转换为,map::value_type因为std::pair有一个构造函数引用其两个组成类型,并且std::string有一个隐式转换构造函数接受一个char const *.

因此,初始化列表构造函数std::map是可行的,并且可以从嵌套的花括号初始化列表中进行构造。

相关的标准存在于§13.3.1.7/1 [over.match.list]

当非聚合类类型的对象T被列表初始化 (8.5.4) 时,重载决议分两个阶段选择构造函数:
— 最初,候选函数是类的初始化列表构造函数 (8.5.4)T和参数list 由作为单个参数的初始值设定项列表组成。
— 如果没有找到可行的初始化列表构造函数,则再次执行重载决议,其中候选函数是类的所有构造函数,T参数列表由初始化列表的元素组成。

第一个项目符号导致为外部支撑初始化列表选择initializer_list构造函数map,而第二个项目符号导致pair为内部支撑初始化列表选择正确的构造函数。

于 2014-07-13T02:25:09.283 回答
2

这是列表初始化。规则可在标准的 §8.5.4[dcl.init.list]/p3 中找到:

类型 T 的对象或引用的列表初始化定义如下:

  • 如果初始值设定项列表没有元素并且 T 是具有默认构造函数的类类型,则该对象是值初始化的。
  • 否则,如果 T 是一个聚合,则执行聚合初始化 (8.5.1)。[示例省略]
  • 否则,如果 T 是 的特化std::initializer_list<E>initializer_list则按如下所述构造对象,并用于根据从相同类型的类 (8.5) 中初始化对象的规则来初始化对象。
  • 否则,如果 T 是类类型,则考虑构造函数。枚举适用的构造函数,并通过重载决议(13.3、13.3.1.7)选择最佳构造函数。如果需要缩小转换(见下文)来转换任何参数,则程序格式错误。
  • [省略规则的示例和其余部分]

请注意,std::initializer_list在这些情况下,重载决议将更喜欢构造函数(§13.3.1.7 [over.match.list])。

因此,当编译器看到一个用于初始化非聚合、非std::initializer_list类类型的对象的花括号列表时,它将执行重载决议以选择适当的构造函数,initializer_list如果存在可行的构造函数,则优先选择构造函数(就像它所做的那样std::map)。

于 2014-07-13T02:25:33.473 回答