当我分配一个成员变量作为大小的数组时,我看到了与我分配一个非成员变量时不同的符号转换警告行为。
如果我用 const int
类型的成员变量创建一个数组,我会得到一个 warning: conversion to 'long unsigned int' from 'const int' may change the sign of the result [-Wsign-conversion]
警告。即使我将成员 static_cast
转换为 long unsigned int
,我也会收到此警告。如果我用 const int
类型的非成员变量初始化数组,我不会收到任何符号转换警告。
我在 Ubuntu 18.04 上用 gcc 7.4.0 看到了这个,只用 g++ -Wsign-conversion main.cpp
编译
例子:
const int sz = 1;
class Foo
{
Foo()
:
m_arr1(new char[sz]), // no warning
m_arr2(new char[static_cast<long unsigned int>(sz)]), // no warning
m_arr3(new char[m_arr_sz]), // warning
m_arr4(new char[static_cast<long unsigned int>(m_arr_sz)]) // warning
{
}
~Foo()
{
delete[] m_arr1;
delete[] m_arr2;
delete[] m_arr3;
delete[] m_arr4;
}
private:
const int m_arr_sz = 1;
char* m_arr1;
char* m_arr2;
char* m_arr3;
char* m_arr4;
};
int main()
{
return 0;
}
初始化是发生在成员初始化器列表中,还是发生在构造函数的主体中,或者被初始化的数组是否是成员似乎都无关紧要。
这是一个错误吗?还是实际上存在一些我不知道的差异?
最佳答案
当你在全局范围内有 const int sz = 1;
时,它是一个常量表达式。这意味着编译器 100% 知道该值是什么,并且它知道由于 sz
的值在无符号整数类型的范围内是可表示的,因此它不会发出警告。
反之,类中的const int m_arr_sz = 1;
不是常量表达式。它是类的成员,如果构造函数中没有给出初始化器,它将被初始化为 1
。这使得该变量成为“运行时变量”,即其值在编译时可能未知的变量。在这种情况下,gcc 将发出警告,因为它不能保证在所有情况下您都会得到正确的行为。是的,在这种微不足道的情况下,它可以进行更深入的静态分析,但这会减慢编译时间。只发出警告会更容易。
关于c++ - 使用成员创建数组时的不同 -Wsign-conversion 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57795161/