为什么 gcc 警告只针对统一初始化缩小转换范围?
Why gcc warns about narrowing conversion only for uniform initialization?
我正在尝试将long
类型变量转换为int
带有uniform initialization
和没有它的类型变量。但是我只在统一初始化时收到编译器警告。为什么?为什么gcc
在这两种情况下都不警告?我也尝试过clang
,并得到了类似的结果。
这是代码
#include <iostream>
int main() {
long l = 1;
int i1 = l;
int i2 = { l };
std::cout << i1 << std::endl;
std::cout << i2 << std::endl;
return 0;
}
也是我收到的唯一一个警告
$ g++ -Wall -Wextra 1.cpp
1.cpp: In function ‘int main()’:
1.cpp:6:16: warning: narrowing conversion of ‘l’ from ‘long int’ to ‘int’ inside { } [-Wnarrowing]
int i2 = { l };
因为标准说,缩小转换限制只为列表初始化指定(自 C++11 起)。
列表初始化通过以下方式限制允许的隐式转换 禁止以下行为:
- 从浮点类型转换为整数类型
从长双精度转换为双精度或浮点- 数以及从双精度到浮点数的转换,除非源是常量表达式 并且不会发生溢出
- 从整数类型转换为浮点类型,除非源是可以存储其值的常量表达式 完全在目标类型中
- 从整数或无作用域枚举类型转换为不能表示原始值的所有值的整数类型,源除外 是一个常量表达式,其值可以精确地存储在 目标类型
对于其他初始化方法(使用括号或等号),不应用(添加)缩小转换限制规则;因为这可能会破坏许多遗留代码。
两者之间的区别在于,在列表初始化中不允许缩小转换范围。在其他形式的初始化中,它们是允许的。
这里经常让人们感到困惑的是,当某些事情不允许时,并不意味着编译器必须拒绝编译代码。要求是编译器必须"发出诊断",警告是一种有效的诊断形式。
因此,编译器需要为列表初始化中的缩小转换发出诊断,这就是您所看到的。除此之外,正如其他人所说,您可以提高警告级别,以获取有关在其他情况下缩小转化范围的警告。但是在列表初始化之外,诊断不是必需的,而且它们通常比有用更烦人,因此默认情况下不打开。
相关文章:
- 是否可以初始化不可复制类型的成员变量(或基类)
- C++使用整数的压缩数组初始化对象
- C++初始化基类
- 多成员Constexpr结构初始化
- 复制列表初始化的隐式转换的等级是多少
- 内联映射初始化的动态atexit析构函数崩溃
- 如何在C++中初始化嵌套类中的2个memeber
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 没有用于初始化C++中的变量模板的匹配构造函数
- 在未初始化映射的情况下,将值插入到映射的映射中
- 为什么 gcc 警告只针对统一初始化缩小转换范围?
- 列表初始化时需要缩小转换范围
- P0960,是否有任何机制可以检测 c++20 中带有 ()s 的新聚合初始化中是否存在缩小?
- 分配列表和初始化器列表之间 C++11 缩小的差异
- 如果第二个属性未支撑,则将与支撑初始化器配对缩小转换
- g++4.9和g++5在初始化列表中缩小时的不同行为
- 在列表初始化中缩小到布尔值的转换 - 奇怪的行为
- 在C++14中,对浮点变量进行双重赋值的统一初始化不会产生缩小错误
- 在初始化列表中初始化联合成员而不缩小
- 尝试初始化 wregex 对象时 boost 的 regex_traits_defaults.hpp 中的缩小转换警告