传递整数文字时没有隐式转换警告吗?

时间:2019-06-19 07:23:25

标签: c++ implicit-conversion

我试图了解隐式转换何时发生,并检测它们以提高代码库的质量。

我为此启用了WconversionWsign-conversion。但是我遇到了编译器没有给出任何错误的情况。示例:

#include <iostream>
#include <array>

int main()
{
   std::array<int, 10> vec{};
   std::cout << vec[1] << std::endl; 
}

编译:

$ g++ --std=c++14 -Wall -Wextra -Werror -pedantic -Wsign-conversion -Wconversion test.cpp 
$ 

数组的大小和到operator[]的索引都应为std::size_t类型(无符号)。但是,我正在传递带符号的文字,似乎没有问题。我什至可以将1.0F传递给operator[],编译器就可以了。

但是,如果我为operator[]的索引创建一个带符号的变量,则编译器会发出有关隐式转换的警告。

幕后到底发生了什么?使用文字时是否发生隐式转换?为什么编译器没有给出错误?我正在Ubuntu 18.04上使用GCC 7.4。

2 个答案:

答案 0 :(得分:8)

编译器不会警告您,因为它在编译时知道安全(即原始值和目标值相同)时会进行转换。当您这样做时:

vec[1.0F]

从编译器的角度来看,1.0F1之间的值(精度损失)没有变化,因此编译器不会警告您。如果您尝试:

vec[1.2F]

...编译器会警告您,因为即使1.2F会转换为1,也会造成精度损失。

如果您使用的是编译时未知的值,例如:

float get_float();

vec[get_float()];

您将得到预期的警告,因为编译器事先不知道get_float()的值,因此无法确定转换是否安全

请注意,当期望使用常量表达式时(例如,std::array<int, 10>),您将永远不会收到这样的警告,因为根据定义,常量表达式在编译时是已知的,因此编译器会知道之间是否存在问题给定值和转换后的值。

答案 1 :(得分:6)

存在警告“将有符号转换为无符号”,因为其中的一些可能会产生不良/意外的结果。将有符号的1转换为无符号的1不会出现任何问题。将-3转换为无符号是有问题的。

使用变量,编译器无法(通常)知道运行时的值,因此必须警告潜在的转换问题。使用文字,它的值在编译时就已知,因此编译器可以默默地做正确的事情(当该值转换为OK时),或者在必要时发出警告/错误提示(当转换有问题时)。