为什么`bool b = 2`运行良好,但是`bool b = {2}`会产生一个缩小转换的警告?

tia*_*anz 7 c++ type-conversion narrowing c++11

使用{}初始化程序C++11初始化会bool b = {2}产生以下警告消息:

warning: narrowing conversion of ‘2’ from ‘int’ to ‘bool’ inside { } [-Wnarrowing]
Run Code Online (Sandbox Code Playgroud)

但是,使用旧样式bool b = 2没有这样的问题.这背后的原因是什么?


更新:我使用编译代码g++ -std=c++11,它给了我警告.如果我添加该选项-pedantic-errors,警告将成为错误.

aar*_*man 8

缩小初始化列表中的数据类型会使您的c ++ 11程序生成错误,在这种情况下,编译器可以发出警告或继续执行.

有趣的是你实际上可以改变它bool b = {1}并且没有警告,我假设因为bool的值保证在整数类型中转换为0和1.

这是确认错误的标准报价.

缩小转换是隐式转换
- 从浮点类型到整数类型,或
- 从long double到double或float,或从double到float,除非source是常量表达式,转换后的实际值是在可以表示的值范围内(即使它不能精确表示),或者
- 从整数类型或无范围枚举类型到浮点类型,除非源是常量表达式和转换后的实际值将适合目标类型,并在转换回原始类型时生成原始值,或
- 从整数类型或未范围的枚举类型到不能表示原始类型的所有值的整数类型,除非源是常量表达式,并且转换后的实际值将适合目标类型并将生成原始值转换回原始类型时.
如上所述,列表初始化中的顶级不允许进行此类转换

  • @Tian Zhou:你有没有使用`-pedantic-errors`? (3认同)

Sha*_*our 5

看起来像:

\n\n
bool b = {2} ;\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果我们查看C++ 标准草案List-initialization第 7段,这确实是一个缩小范围的转换8.5.4

\n\n
\n

缩小转换是隐式转换

\n
\n\n

并包括以下项目符号(强调我的):

\n\n
\n

从整数类型或无作用域枚举类型到无法表示原始类型的所有值的整数类型\n,除非源是常量表达式,其值在整数提升后将适合目标类型。

\n
\n\n

bool无法表示该值2,因此这是最严格意义上的缩小转换。这是有道理的,初始化的全部目的{}防止隐式转换并提高类型安全性。哪个是老款您在这里提到的

\n\n
bool b = 2\n
Run Code Online (Sandbox Code Playgroud)\n\n

这取决于4.12 布尔转换部分部分,其中表示:

\n\n
\n

[...] 零值、空指针值或空成员指针值\n 被转换为 false;任何其他值都会转换为 true。[...]

\n
\n\n

当然,缩小转换{2}的整个前提依赖于truefalse的值为和的假设,据我所知,标准中并不能保证这一点。虽然它暗示了标准在转换中承诺的唯一事情,但如果我们要使用文字,我们不需要依赖这个假设,我们有两个完美的布尔文字10truefalse就是您应该使用的。

\n\n

为了完整起见,这种缩小转换的格式正确,它需要诊断,因此警告错误都是可以接受的。如果我们看一下第 3段,它说:

\n\n
\n

类型 T 的对象或引用的列表初始化定义如下:

\n
\n\n

并包括以下项目符号(重点是我的):

\n\n
\n

否则,如果初始值设定项列表具有类型 E 的单个元素,并且 T 不是引用类型或其引用类型与 E 引用相关,则从该元素初始化对象或引用;如果需要缩小转换(见下文)将元素转换为 T,则程序格式错误

\n
\n\n

并包括以下示例:

\n\n
[ Example:\n  int x1 {2}; // OK\n  int x2 {2.0}; // error: narrowing\n\xe2\x80\x94end example ]\n
Run Code Online (Sandbox Code Playgroud)\n