错误的std::vector构造函数

4

我在编译一行看似简单的代码时,Clang报出了一个奇怪的错误。

以下代码会产生错误:

size_t s = 5;
std::vector<double> bestScores{s, -1.0};

我想使用构造函数#2来用五个-1.0值填充一个新的向量。我得到的错误是“非常量表达式不能从类型 'size_type'(又名 'unsigned long')缩小为' double '在初始化器列表中。”发生了什么?以下代码编译良好:
std::vector<double> bestScores{5, -1.0};

它是否试图使用初始化列表构造函数?我以为您需要两个花括号:

std::vector<double> bestScores{{5, -1.0}};

3
除了std::array因为混淆和陈旧的原因,初始化列表构造函数不需要两个花括号。 - Mooing Duck
@MooingDuck 那一定是我在想的。谢谢。 - Rag
2
也许你应该阅读C++11-统一初始化,特别是最后两段。 - Jonathon Reinhart
2个回答

10
问题在于您正在使用花括号括起来的初始化列表构造向量。这会优先选择适用于 std::initializer_list<T> 的构造函数。在这种情况下,size_t-1.0 列表与 std::initializer_list<double> 兼容,因此选择了该构造函数。您需要使用旧式的 C++03 构造方法:
std::vector<double> bestScores(s, -1.0);

这是花括号初始化的一个陷阱之一。它们对某些标准库容器实例化不起作用。您必须记住,std::initializer_list构造函数将优先于其他构造函数。


为什么在选择构造函数时,它会认为 size_tdouble 是兼容的,然后在后续过程中抛出编译时的“缩小转换”错误?C++ 是否存在非自洽性错误或者这是因为其严格的向后兼容性而产生的怪异行为? - Mark Jeronimus

6
问题在于当一个类有一个std::initializer_list构造函数时,如果参数可以转换为initializer_list的类型(本例中的double),则使用统一初始化语法时会优先选择该构造函数。请参见programmers.stackexchange.com上的详细回答。
目前,您的解决方案是使用带括号的非统一语法。这意味着它不会考虑std::initializer_list构造函数,并在此情况下执行您想要的操作。 std::vector<double> bestScores(s, -1.0)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接