7

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

warning: narrowing conversion of ‘2’ from ‘int’ to ‘bool’ inside { } [-Wnarrowing]

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


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

4

2 回答 2

8

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

有趣的是,您实际上可以将其更改为bool b = {1}并且没有警告,我假设因为 bool 的值保证转换为整数类型的 0 和 1。

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

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

于 2013-11-02T01:19:29.763 回答
4

看起来像:

bool b = {2} ;

如果我们查看草案 C++ 标准部分List-initialization7段,这确实是一个缩小转换8.5.4

缩小转换是隐式转换

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

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

bool不能表示值2,所以这是最严格意义上的缩小转换。{}初始化的全部意义在于防止隐式转换并提高类型安全性。您在此处引用的旧样式依赖于:

bool b = 2

这取决于4.12 布尔转换部分,它说:

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

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

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

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

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

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

并包括以下示例:

[ Example:
  int x1 {2}; // OK
  int x2 {2.0}; // error: narrowing
—end example ]
于 2013-11-02T01:43:08.330 回答