# V730. Not all members of a class are initialized inside the constructor.

Анализатор обнаружил конструктор, который по всей видимости инициализирует не все члены класса.

Рассмотрим простой синтетический пример:

    struct MyPoint
    {
      int m_x, m_y;
      MyPoint() { m_x = 0; }
      void Print() { cout << m_x << " " << m_y; }
    };
    MyPoint Point;
    Point.Print();

При создании объекта Point вызовется конструктор, в котором не инициализируется член m_y. Соответственно при вызове функции Print будет использована неинициализированная переменная, и последствия этого непредсказуемы.

Корректный конструктор может выглядеть следующим образом:

    MyPoint() { m_x = 0; m_y = 0; }

Мы рассмотрели простой синтетический пример, где сразу всё понятно. Однако в реальном коде всё бывает гораздо сложнее. Поиск неинициализированных членов класса является набором эмпирических алгоритмов. Во-первых, члены классов можно инициализировать разнообразнейшими способами, и анализатор не всегда может понять, инициализирован член класса или нет. Во-вторых, не всегда нужно инициализировать все члены, и сообщения анализатора могут быть ложными, так как он не может угадать задумку программиста.

Поиск неинициализированных членов класса является сложным и неблагодарным занятием. Подробнее этот вопрос рассмотрен в статье: "Поиск неинициализированных членов класса". Поэтому просим в случае ложных срабатываний отнестись к анализатору с пониманием и использовать один из механизмов подавления ложных срабатываний.

Вы можете подавить предупреждение, отметив конструктор комментарием "//-V730". Вы также можете использовать базу данных для разметки ложных предупреждений. В крайнем случае, если ложных срабатываний слишком много, то разумно полностью отключить диагностику V730.

Однако это крайние меры. На практике разумно отключать анализ отдельных членов структур, не требующих инициализации в конструкторе. Рассмотрим искусственный пример:

    const size_t MAX_STACK_SIZE = 100;

    class Stack
    {
      size_t m_size;
      int m_array[MAX_STACK_SIZE];
    public:
      Stack() : m_size(0) {}
      void Push(int value)
      {
        if (m_size == MAX_STACK_SIZE)
          throw std::exception("overflow");
        m_array[m_size++] = value;
      }
      int Pop()
      {
        if (m_size == 0)
          throw std::exception("underflow");
        return m_array[--m_size];
      }
    };

Этот класс реализует стек. Массив 'm_array' не инициализируется в конструкторе и это корректно, так как изначально стек считается пустым.

Анализатор выдаст предупреждение V730, так как не может понять принцип работы этого класса. Вы можете подсказать анализатору, пометив член 'm_array' комментарием "//-V730_NOINIT". Это укажет анализатору, что массив 'm_array' не требуется обязательно инициализировать.

Теперь, анализируя класс:

    class Stack
    {
      size_t m_size;
      int m_array[MAX_STACK_SIZE];  //-V730_NOINIT
    public:
      Stack() : m_size(0) {}
      .....
    };

Анализатор не выдаст предупреждение.

Существует способ отключить предупреждения V730 на все поля классов определённого типа.

Рассмотрим пример:

    class Field
    {
      public:
      int f;
    };

    class Test
    {
    public:
      Test() {}
      Field field;
    };

На этом фрагменте кода будет выдано предупреждение: V730 Not all members of a class are initialized inside the constructor. Consider inspecting: field.

Чтобы исключить все предупреждения поля класса типа 'Field', следует добавить следующий комментарий в код или файл настроек:

    //+V730:SUPPRESS_FIELD_TYPE, class:Field

Формат комментария:

    //+V730:SUPPRESS_FIELD_TYPE, class:className, namespace:nsName

или

    //+V730:SUPPRESS_FIELD_TYPE, class:className.NestedClassName, namespace:nsName

Данная диагностика классифицируется как:

CWE-457 CERT-EXP53-CPP

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V730.