我遇到了我认为很奇怪的事情:
#include <vector>
int numqueues = 1;
std::vector<float> priorities{numqueues, 1.f };
//^^^ warning: narrowing conversion of numqueues from int to float
//std::vector<float> priorities(numqueues, 1.f );
//^^^ No warning or error. And it's not because it's parsed as a function declaration
// as I can call push_back in main.
int main()
{
priorities.push_back(1);// No narrowing conversion needed
}
我用几个编译器试过这个,这不会编译。
编辑:据说 initializer_list 优先,看起来是这样,但我试图模仿 std::vector 并且在这个例子中我没有得到缩小转换错误:
#include <vector>
#include <iostream>
#include <initializer_list>
template <typename T>
class MyVector
{public:
MyVector(size_t s, float f) {
std::cout << "Called constructor\n";
}
MyVector(std::initializer_list<T> init)
{
std::cout << "Called initializer list constructor\n";
}
};
int main()
{
MyVector<float> foo{ size_t(3), 2.f };
}
我做了完全一样的事情,用 size_t 和 float 初始化它,就像在另一个例子中一样,这个编译得很好。
在本声明中
std::vector<float> priorities{numqueues, 1.f };
编译器使用初始化列表构造函数。
vector(initializer_list<T>, const Allocator& = Allocator());
禁止初始化列表的缩小转换。
在本声明中
std::vector<float> priorities(numqueues, 1.f );
编译器使用指定元素数量及其初始值设定项的构造函数。
vector(size_type n, const T& value, const Allocator& = Allocator());
来自 C++ 14 标准(8.5.4 列表初始化)
2 如果构造函数的第一个参数是 std::initializer_list 类型或对某些类型 E 的可能具有 cv 限定的 std::initializer_list 的引用,并且没有其他参数或所有其他参数具有默认值,则构造函数是初始化列表构造函数参数(8.3.6)。[注意:在列表初始化中,Initializer-list 构造函数比其他构造函数更受青睐
和(13.3.1.7 通过列表初始化进行初始化)
1 当非聚合类类型 T 的对象被列表初始化使得 8.5.4 指定根据本节中的规则执行重载决议时,重载决议分两个阶段选择构造函数:
(1.1) — 最初,候选函数是类 T 的初始化列表构造函数 (8.5.4),参数列表由初始化列表作为单个参数组成。
(1.2) — 如果找不到可行的初始化列表构造函数,则再次执行重载解析,其中候选函数是类 T 的所有构造函数,参数列表由初始化列表的元素组成。
这是一个演示程序
#include <iostream>
#include <initializer_list>
struct A
{
A( std::initializer_list<float> )
{
std::cout << "A( std::initializer_list<float> )\n";
}
A( size_t, float )
{
std::cout << "A( size_t, float )\n";
}
};
int main()
{
A a1 { 1, 1.0f };
A a2( 1, 1.0f );
return 0;
}
程序输出是
A( std::initializer_list<float> )
A( size_t, float )
至于你附加的问题(8.5.4 List-initialization)
7 收缩转换是隐式转换
(7.3) — 从整数类型或无作用域枚举类型到浮点类型,除非源是常量表达式并且转换后的实际值将适合目标类型,并在转换回原值时产生原始值原始类型,或
所以在这个列表初始化
MyVector<float> foo{ size_t(3), 2.f };
使用size_t( 3 )
适合类型 float的常量表达式。
例如,如果在上面的演示程序中,您将编写
size_t n = 1;
A a1{ n, 1.0f };
那么编译器应该会发出关于缩小转换的消息(至少 MS VS 2019 C++ 编译器会发出这样的错误消息)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句