C++ 为什么双空大括号{{}会创建std::initializer\u list<;双倍>;只有一个元素,而不是零?
我有以下构造函数:C++ 为什么双空大括号{{}会创建std::initializer\u list<;双倍>;只有一个元素,而不是零?,c++,initializer-list,C++,Initializer List,我有以下构造函数: MyItem(std::initializer_list<double> l) { std::cout << "l size " << l.size() << ")" << std::endl; } l.size()给出的结果是1 这种行为背后的机制是什么 嵌套的{}看起来像是唯一元素的默认构造函数,但我不太明白类型推断在这里的工作原因和方式。当您使用大括号(列表初始化)初始化MyItem对象时,您显示的列
MyItem(std::initializer_list<double> l) {
std::cout << "l size " << l.size() << ")" << std::endl;
}
l.size()给出的结果是1
这种行为背后的机制是什么
嵌套的{}看起来像是唯一元素的默认构造函数,但我不太明白类型推断在这里的工作原因和方式。当您使用大括号(列表初始化)初始化MyItem
对象时,您显示的列表构造函数非常贪婪
这些将传递一个空列表:
MyItem foo({});
MyItem foo{std::initializer_list<double>{}};
这是因为在某些上下文中,您可以简单地使用大括号代替已知类型。这里,它通过首选列表构造函数知道给定的列表应该包含double
为了完整性,这看起来像是传递了一个空列表,但如果它有一个默认构造函数(或者在特殊情况下,做了一些几乎等价的事情),它实际上会初始化foo
。如果没有默认构造函数,它将选择列表构造函数
这句话
MyItem{{}}
表示显式类型转换(函数表示法)
根据C++标准(5.2.3显式转换(函数表示))< /P>
MyItem(std::initializer_list<double> l) {
std::cout << "l size " << l.size() << ")" << std::endl;
}
因此,构造函数将获得一个包含一个元素的初始值设定项列表
{ {} }
double类型的标量对象可以用空括号{}
初始化
结果,表达式创建了一个类型为
MyItem
的临时对象,该对象由初始值设定项列表初始化,该初始值设定项列表包含一个类型为double的元素,该元素的值通过空大括号初始化。您知道它是如何精确推断该类型的吗?{}是否扮演默认构造函数的角色?没有指定类型或auto
。我对机械感兴趣,比如编译器推断它的步骤。@NikolayPolivanov,这可能是最棘手的上下文,在这种上下文中允许使用大括号。一般来说,当您重复类型并且编译器已经知道它时,它们是允许的。例如,您有voidfoo(string)
。假设您希望传递“abcde”的前n个字符,其中n是一个变量。您通常会执行类似于foo(string(“abcde”,n))的操作代码>。但是,它显然是一个字符串,那么为什么要重复该类型呢<代码>foo({“abcde”,n})使用{}
时,通常是值初始化,通常为0或默认构造函数<代码>foo({})代码>传递一个空字符串。即使如此,列表构造函数还是非常贪婪。例如,std::string
有一个列表构造函数,它获取char
的列表。如果你做了foo({5,'A'})代码>,您可能希望得到一个包含五个a字符的字符串(AAAAA),因为有一个用于该字符串的构造函数。然而,即使5不是一个字符
,它仍然可以转换为一个,这意味着您实际得到的字符值为5(可能是一个控制字符),后跟一个a。这就是这些字符的贪婪程度。(const char*,size\t)
调用之所以有效,是因为“abcde”
不能转换为char
知道用大括号制作字符串
——它只能是一种类型!同样,有一条规则说,MyItem foo{{}如果可能的话,code>调用将从元素(这里仅是内部的{}
)创建一个初始值设定项列表
。还有一条规则说,要从{}
中生成一个双精度的,您得到的值是0.0。将这些元素放在一起,您可以看到可以创建一个初始值设定项列表
-一个元素,其中{}
被转换为0.0。谢谢。只需从1元素示例中取消单击,就可以使用3 doubleMyItem{{},{},{}}
创建初始值设定项\u列表-这样它就可以从模板参数中知道类型
MyItem{{}}
MyItem(std::initializer_list<double> l) {
std::cout << "l size " << l.size() << ")" << std::endl;
}
MyItem( {{}} );
{ {} }