代码之家  ›  专栏  ›  技术社区  ›  ks1322

为什么GCC警告只针对统一初始化缩小转换范围?

  •  3
  • ks1322  · 技术社区  · 6 年前

    我正在努力改变信仰 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 };
    
    2 回复  |  直到 6 年前
        1
  •  4
  •   songyuanyao    6 年前

    因为标准规定, narrowing conversions limit 仅用于列表初始化(因为C++ 11)。

    列表初始化将允许的隐式转换限制为 禁止以下行为:

    • 从浮点类型转换为整数类型
    • 从long double到double或float的转换以及从double到float的转换,除非源是常量表达式 不会发生溢出
    • 从整数类型转换为浮点类型,除非源是可存储值的常量表达式 完全在目标类型中
    • 从整数或非范围枚举类型转换为不能表示原始值的所有值的整数类型,除非源 是一个常量表达式,其值可以精确存储在 目标类型

    对于其他初始化方法(使用括号或等号),不应用(添加)缩小转换限制规则;因为这可能会破坏许多遗留代码。

        2
  •  2
  •   Pete Becker    6 年前

    两者的区别在于列表初始化中不允许进行收缩转换。在其他形式的初始化中,它们是允许的。

    这里经常让人困惑的是,当某些东西不被允许时,并不意味着编译器必须拒绝编译代码。要求编译器必须“发出诊断”,警告是有效的诊断形式。

    所以编译器需要对列表初始化中的收缩转换发出诊断,这就是您看到的。除此之外,正如其他人所说,您可以提高警告级别,以获得有关在其他上下文中缩小转换范围的警告。但是不需要列表外的初始化诊断,而且它们通常比有用更烦人,因此默认情况下不打开。