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

标签 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;
}

初始化是发生在成员初始化器列表中,还是发生在构造函数的主体中,或者被初始化的数组是否是成员似乎都无关紧要。

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

最佳答案

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

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

关于c++ - 使用成员创建数组时的不同 -Wsign-conversion 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57795161/

相关文章:

c - 需要帮助解决警告 : dereferencing type-punned pointer will break strict-aliasing rules

c++ - linux浮点_control87替换

c++ - 为什么向 vector 添加元素时其大小相同?

c++ - 向 std::list 添加新元素的复杂性

c++ - 玩转字符数组

c++ - 访问静态和非静态的模板构造函数和函数

c - AVR-GCC 链接器 : "Data"-Section overflows

c - 为什么 gcc 忽略 'register' 对一个 int 变量的请求并接受另一个 int 变量的请求

c++ - MSVC 10 + Luabind + std::vector == 拒绝编译

c - 如何在 ubuntu 中计算 C 程序的运行时间