使用成员创建数组时,不同的-Wsign-conversion行为

时间:2019-09-04 20:18:09

标签: c++ gcc

当我分配带有成员变量作为大小的数组时,与非成员变量分配时,我看到了不同的符号转换警告行为。

如果我创建一个成员类型为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;
}

初始化是否发生在成员初始值设定项列表或构造函数的主体中,或者初始化的数组是否为成员似乎并不重要。

这是一个错误吗?还是实际上有些我不知道的差异?

1 个答案:

答案 0 :(得分:2)

在全局范围内有const int sz = 1;时,它是一个常量表达式。这意味着编译器知道该值是100%,并且知道sz的值在无符号整数类型的范围内是可预设的,因此不会发出警告。

相反,类中的const int m_arr_sz = 1;不是常量表达式。它是该类的成员,如果在构造函数中未提供初始化程序,它将被初始化为1。这使变量成为“运行时变量”,即在编译时其值可能未知的变量。既然是这种情况,gcc将发出警告,因为它不能保证在所有情况下都能获得正确的行为。是的,在这种琐碎的情况下,它可以进行更深入的静态分析,但是这会减慢编译时间。发出警告更容易。