为什么只有在括号初始化对象时才需要从 int 到 float 的缩小转换?

斑马鱼

我遇到了我认为很奇怪的事情:

#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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如果在三元运算符中使用局部变量,为什么从int到short的缩小转换不起作用

在Go中将float转换为int时如何舍入到最接近的int

为什么显式类型转换需要从double到float而不是从int到byte?

类型转换int指针到float指针

为什么仅在列表初始化的情况下才会出现缩小转换警告?

列表初始化时需要缩小转换

在所有平台和处理器体系结构中,从float到int的转换是否一致?

从“浮动”到“ int”的缩小转换无效

不一致的警告“从'const unsigned char'转换为'const float'需要缩小转换范围”

从':: size_t'到'int'的转换需要缩小的转换

从int转换gl_VertexID到float非常慢

这个int到float转换到底是怎么回事,为什么它不正确?

为什么缩小转换范围不能防止错误类型的map.insert()失败?

从十进制类型到单一类型的转换是缩小转换还是扩大转换?

使用初始化程序列表时,缩小转换范围是什么?

当我们将int转换为float到int时,适合int溢出的正确方法

从'long'到有符号类型'char'的缩小转换是实现定义的(C语言中的strtol函数)

从int到float并返回时的符号变化

在C ++中简单的int到float转换

从int到short的缩小

从 float 转换为 int 时的舍入错误

Float 到 Int 转换时崩溃

缩小从 int 到 unsigned char 的转换

错误 C2397:从“int”到“unsigned int”的转换需要缩小转换

快速 int 到 float 转换

使用 P-RNG 时需要缩小转换

为什么在从 double 转换为 float 时,支撑初始化不会引发缩小错误?

从 float(数字)到 int 的隐式转换会丢失精度

为什么在添加短裤时会出现从 int 到 short 的缩小转换警告?(C++)