从C++11开始,标准库容器和std::string就让构造函数接受初始化程序列表.此构造函数优先于其他构造函数(如@约翰内斯堡pointed litb在注释中指出的,甚至忽略了其他“最佳匹配”标准)。这将导致在将所有带括号的构造函数的()形式转换为其带括号的{}版本时出现一些众所周知的缺陷。
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>
void print(std::vector<int> const& v)
{
std::copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, ","));
std::cout << "\n";
}
void print(std::string const& s)
{
std::cout << s << "\n";
}
int main()
{
// well-known
print(std::vector<int>{ 11, 22 }); // 11, 22, not 11 copies of 22
print(std::vector<int>{ 11 }); // 11, not 11 copies of 0
// more surprising
print(std::string{ 65, 'C' }); // AC, not 65 copies of 'C'
}我在这个站点上找不到第三个例子,在Lounge聊天中(在与@ count折叠、@Abyx和@JerryCoffin的讨论中),有点令人惊讶的是,将接受计数和字符的std::string构造函数转换为使用{}而不是()的字符,将其含义从字符的n副本更改为n-th字符(通常来自ASCII表),然后是其他字符。
这不是通常禁止缩小转换的大括号,因为65是一个常量表达式,可以表示为char,并在转换回int时保留其原始值(§8.5.4/7,项目4) (感谢@JerryCoffin)。
问题:在标准库中是否还有更多将()样式构造函数转换为{}样式的示例,是否有初始化-列表构造函数贪婪地匹配?
发布于 2013-11-07 22:43:24
我想,在std::vector<int>和std::string的示例中,您还打算涵盖其他容器,例如std::list<int>、std::deque<int>等,这些容器显然与std::vector<int>有相同的问题。同样,int并不是唯一的类型,因为它也适用于char、short、long及其unsigned版本(可能还有其他一些完整的类型)。
我认为也有std::valarray<T>,但我不确定是否允许T为整数类型。实际上,我认为它们有不同的语义:
std::valarray<double>(0.0, 3);
std::valarray<double>{0.0, 3};还有其他一些标准的C++类模板,它们都以std::initializer_list<T>作为参数,但我认为这些模板中没有一个具有重载的构造函数,在使用括号而不是大括号时将使用该构造函数。
https://stackoverflow.com/questions/19847960
复制相似问题