当我分配带有成员变量作为大小的数组时,与非成员变量分配时,我看到了不同的符号转换警告行为。
如果我创建一个成员类型为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;
}
初始化是否发生在成员初始值设定项列表或构造函数的主体中,或者初始化的数组是否为成员似乎并不重要。
这是一个错误吗?还是实际上有些我不知道的差异?
答案 0 :(得分:2)
在全局范围内有const int sz = 1;
时,它是一个常量表达式。这意味着编译器知道该值是100%,并且知道sz
的值在无符号整数类型的范围内是可预设的,因此不会发出警告。
相反,类中的const int m_arr_sz = 1;
不是常量表达式。它是该类的成员,如果在构造函数中未提供初始化程序,它将被初始化为1
。这使变量成为“运行时变量”,即在编译时其值可能未知的变量。既然是这种情况,gcc将发出警告,因为它不能保证在所有情况下都能获得正确的行为。是的,在这种琐碎的情况下,它可以进行更深入的静态分析,但是这会减慢编译时间。发出警告更容易。