use*_*113 4 c++ implicit-conversion
我试图了解隐式转换何时发生,并检测它们以提高代码库的质量。
我已经启用Wconversion,并Wsign-conversion为这个。但是我遇到了编译器没有给出任何错误的情况。例:
#include <iostream>
#include <array>
int main()
{
std::array<int, 10> vec{};
std::cout << vec[1] << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
编译:
$ g++ --std=c++14 -Wall -Wextra -Werror -pedantic -Wsign-conversion -Wconversion test.cpp
$
Run Code Online (Sandbox Code Playgroud)
数组的大小和索引to operator[]都应为std::size_t(无符号)类型。但是,我正在传递带符号的文字,似乎没有问题。我什1.0F至可以传递给operator[]编译器。
operator[]但是,如果我为to的索引创建一个带符号的变量,则编译器会发出有关隐式转换的警告。
到底发生了什么事?使用文字时是否发生隐式转换?为什么编译器没有给出错误?我在Ubuntu 18.04上使用GCC 7.4。
编译器不会警告您,因为它在编译时知道此转换是否安全,即原始值和目标值相同。当您这样做时:
vec[1.0F]
Run Code Online (Sandbox Code Playgroud)
从编译器的角度来看,1.0F和之间的值没有变化(精度损失)1,因此编译器不会警告您。如果你试试:
vec[1.2F]
Run Code Online (Sandbox Code Playgroud)
...编译器会警告您,因为即使1.2F将其转换为1,也会导致精度损失。
如果使用编译时未知的值,例如:
float get_float();
vec[get_float()];
Run Code Online (Sandbox Code Playgroud)
您将得到预期的警告,因为编译器get_float()事先不知道值,因此无法确定转换是安全的。
请注意,当期望使用常量表达式时(例如in中std::array<int, 10>),您永远不会收到这样的警告,因为根据定义,常量表达式是在编译时已知的,因此编译器知道给定值和转换后的值之间是否存在问题。
存在警告“将有符号转换为无符号”,因为其中某些转换可能会产生不良/意外的结果。将带1符号的转换为无符号的结果1没有任何问题。转换-3为无符号是有问题的。
使用变量,编译器不能(通常)知道运行时的值,因此必须警告潜在的转换问题。使用文字,它的值在编译时是已知的,因此编译器可以默默地做正确的事(当值转换为OK时),或在必要时发出警告/错误(当转换有问题时)。