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

No implicit conversion warnings when passing integer literals?

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

我为此启用了 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

警告 "converting signed to unsigned" 存在是因为 一些 这些转换可以产生 bad/unexpected 结果。将有符号的 1 转换为无符号的结果 1 没有任何问题。将 -3 转换为无符号是有问题的。

对于变量,编译器无法(在一般情况下)知道它在运行时的值,因此它必须警告潜在的转换问题。对于文字,它的值在编译时是已知的,因此编译器可以默默地做正确的事情(当值转换正常时),或者在必要时 warn/error out(当转换有问题时)。

编译器不会警告你,因为它知道在编译时这个转换如果安全,即原始值和目标值是相同的。当你这样做时:

vec[1.0F]

在编译器 point-of-view 中,1.0F1 之间没有值变化(精度损失),因此编译器不会警告您。如果你尝试:

vec[1.2F]

...编译器会警告您,因为尽管 1.2F 将转换为 1,但存在精度损失。

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

float get_float();

vec[get_float()];

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

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