为何`float value{4.0};`不被视为窄化转换?
将一种数据类型转换为另一种数据类型,如果这一操作过程可能导致数据丢失,那么这种转换操作就被叫做窄化转换(narrowing cast)。
例如,将浮点数3.14
储存为int
将导致.14
丢失,只剩下3
。
使用统一初始化(uniform initialization)可以避免窄化转换。如果发生了窄化转换,将会编译失败。
问题
根据C++标准,字面量3.14
的类型是double
(从上面一段代码的报错信息中也能得知)。那代码float value{4.0};
不是将双精度浮点数窄化转换为单精度浮点数了吗?为什么能正常运行呢?
float value{4.0};
不是窄化转换。
浮点数4.0
可以被精确表示为一个float
类型的值,不会发生精度丢失。
由于精度不会丢失,所以尽管float
相对于double
是一个“窄”类型,编译器仍然允许这种转换。
但是,下面这段代码(应当)是会编译出错的:
编译结果:
g++给出一个warning,但编译成功:
MSVC编译出错:
我的理解是,valueDouble
的值是3.1400000000000001e+0
,valueFloat
的值是3.1400001e+0f
,所以从valueDouble
转换到valueFloat
发生了精度下降,所以是窄化转换,所以编译出错;而double
类型的3.14
转换到float
类型后,精度并没有下降,所以不是窄化转换。