为什么gcc警告仅缩小统一初始化的转换范围?

时间:2018-07-24 11:08:48

标签: c++ c++11 language-lawyer compiler-warnings uniform-initialization

我正在尝试将uniform initialization和不包含long类型的变量转换为int类型的变量。但是我只有在统一初始化时才收到编译器警告。这是为什么?为什么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 个答案:

答案 0 :(得分:4)

由于该标准规定,narrowing conversions limit仅用于列表初始化(自C ++ 11起)。

  

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

     
      
  • 从浮点类型到整数类型的转换
  •   
  • 从长整型转换为双精度或浮点型,以及从双精度转换为浮点型,除非源是常量表达式   并且不会发生溢出
  •   
  • 从整数类型到浮点类型的转换,除非源是可以存储值的常量表达式   完全符合目标类型
  •   
  • 从整数或无作用域枚举类型到不能代表原始值的所有整数类型的转换,除非source   是一个常数表达式,其值可以精确地存储在   目标类型
  •   

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

答案 1 :(得分:2)

两者之间的区别在于列表初始化中不允许缩小转换。在其他形式的初始化中,允许使用它们。

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

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

相关问题