在C++11中,初始化std::map<std::string, int>似乎是合法的,如下所示:
std::map<std::string, int> myMap = {
{ "One", 1 },
{ "Two", 2 },
{ "Three", 3 }
};直观地说,这是有意义的--大括号括起来的初始化器是一对字符串的列表,而std::map<std::string, int>::value_type是std::pair<std::string, int> (可能有一些const限定条件)。
但是,我不太清楚这里的输入是如何工作的。如果我们在这里删除变量声明,只使用大括号括起来的初始化器,编译器就不会知道它在查看std::initializer_list<std::pair<std::string, int>>,因为它不知道带大括号的对代表std::pair。因此,编译器似乎在某种程度上推迟了将类型分配给大括号--封闭的初始化器的行为,直到从std::map构造函数获得足够的类型信息,从而认识到嵌套的大括号是用于对的。我不记得在C++03中发生过这样的事情;据我所知,表达式的类型从来不取决于它的上下文。
哪些语言规则允许此代码正确编译,并允许编译器确定用于初始化程序列表的类型?我希望得到关于C++11规范的具体参考答案,因为这真的很有趣!
谢谢!
发布于 2014-07-13 02:25:09
在表达中
std::map<std::string, int> myMap = {
{ "One", 1 },
{ "Two", 2 },
{ "Three", 3 }
};在右边,您有一个大括号-init-列表,其中每个元素也是一个大括号-init-列表。发生的第一件事是考虑std::map的初始化器列表构造函数。
map(initializer_list<value_type>,
const Compare& = Compare(),
const Allocator& = Allocator());map<K, V>::value_type是pair<const K, V> (在本例中为pair<const string, int> )的类型胡枝子。可以成功地将内部大括号-init-列表转换为map::value_type,因为std::pair有一个引用其两个组成类型的构造函数,而std::string有一个接受char const *的隐式转换构造函数。
因此,std::map的初始化程序列表构造函数是可行的,并且可以从嵌套的大括号列表中进行构造。
相关标准载于第13.3.1.7/1节over.match.list。
当非聚合类类型的对象
T被初始化(8.5.4)时,重载解析分两个阶段选择构造函数: -最初,候选函数是类T的初始化-列表构造函数(8.5.4),参数列表由作为单个参数的初始化程序列表组成。 -如果找不到可行的初始化程序列表构造函数,则再次执行重载解析,其中候选函数是类T的所有构造函数,参数列表由初始化程序列表的元素组成。
第一个项目导致为外部大括号-init-列表选择map的map构造函数,而第二个项目导致为内部大括号-init-列表选择正确的pair构造函数。
发布于 2014-07-13 02:25:33
这是列表初始化。这些规则载于标准的第8.5.4dcl.init.list/p3节:
列表-对象或T类型引用的初始化定义如下:
std::initializer_list<E>的专门化,则按照下面描述的方式构造initializer_list对象,并根据从同一类型的类(8.5)初始化对象的规则对对象进行初始化。注意,在这种情况下,重载解析将更倾向于std::initializer_list构造函数(§13.3.1.7 over.match.list)。
因此,当编译器看到用于初始化非聚合、非std::initializer_list类类型的对象的大括号列表时,它将执行过载解析以选择适当的构造函数,如果存在可行的构造函数(就像对std::map一样),则更倾向于initializer_list构造函数。
https://stackoverflow.com/questions/24718555
复制相似问题