3

每个 C++ 教程很早就提到了两件事:

  1. 在可能的情况下,大括号初始化通常更优越,因为它会在缩小转换期间抛出错误,例如
int narrow{1.7}; // error: narrowing conversion of '1.7e+0' from 'double' to 'int'
  1. 您必须将浮点数显式声明为浮点字面量,否则它们将默认为双精度字面量
float some_float{1.7f};

然而,在 Windows 上使用 g++ 编译器时,我发现了一些奇怪的东西——

float narrow{1.7}; // still a float despite no f postfix
double not_narrow{1.7}; // actually a double

此代码编译没有任何错误,并sizeof(narrow)返回 4,其中sizeof(not_narrow)返回 8,如预期的那样。
将鼠标悬停在 1.7 上时,VSCode 将其识别为双字面值 ~=1.699999999999999956,但浮点数随后将其缩小到 ~=1.700000048。
我认为这可能只是 1.7 既可以作为浮点数也可以作为双精度数,所以我尝试了

float narrow{1.699999999999999956};

但这会产生相同的结果。
为什么支撑初始化不在这里抛出错误(警告,诊断消息,任何东西)以将双字面值缩小为浮点数?这是 g++ 特有的,还是一般 C++ 的怪癖?我很想更好地理解。

4

1 回答 1

8

从浮点类型到更短的浮点类型的转换如果“源是一个常量表达式并且转换后的实际值在可以表示的值的范围内(即使它不能准确表示)”(C++20 [dcl.init.list]/7.2)。

如果你仔细想想,double{1.7}float{1.7}可能两者都不准确。但是,如果您写后者,则可以合理地假设您是认真的,并且禁止这样做并没有什么好处。

于 2021-09-06T22:14:13.487 回答