Правильный способ инициализации структур C++


наш код включает в себя структуру POD (простая старая структура данных) (это базовая структура c++, в которой есть другие структуры и переменные POD, которые должны быть инициализированы в начале.)

основываясь на том, что у меня есть читать кажется, что:

myStruct = (MyStruct*)calloc(1, sizeof(MyStruct));

следует инициализировать все значения до нуля, как это делает:

myStruct = new MyStruct();

однако, когда структура инициализируется вторым способом, Valgrind позже жалуется "условный прыжок или перемещение зависит от неинициализированные значения" при использовании этих переменных. Является ли мое понимание ошибочным здесь, или Valgrind бросает ложные срабатывания?

5 56

5 ответов:

В C++ классы / структуры идентичны (с точки зрения инициализации).

структура non POD может также иметь конструктор, чтобы он мог инициализировать члены.
Если ваша структура является POD, то вы можете использовать инициализатор.

struct C
{
    int x; 
    int y;
};

C  c = {0}; // Zero initialize POD

в качестве альтернативы вы можете использовать конструктор по умолчанию.

C  c = C();      // Zero initialize using default constructor
C* c = new C();  // Zero initialize a dynamically allocated object.

// Note the difference between the above and the initialize version of the constructor.
// Note: All above comments apply to POD structures.
C  c;            // members are random
C* c = new C;    // members are random (more officially undefined).

Я считаю, что valgrind жалуется, потому что именно так работал C++. (Я не совсем уверен, когда C++ был обновлен с нулевой инициализацией по умолчанию строительство.) Лучше всего добавить конструктор, который инициализирует объект (структуры разрешены конструкторы).

в качестве примечания:
Многие новички пытаются оценить init:

C c(); // Unfortunately this is not a variable declaration.

// The correct way to do this is:
C c = C();

быстрый поиск "самого досадного разбора" даст лучшее объяснение, чем я могу.

из того, что Вы нам сказали, это действительно кажется ложным положительным в valgrind. Элемент new синтаксис с () должно значение-инициализировать объект, предполагая, что это POD.

возможно ли, что какая-то часть вашей структуры на самом деле не является POD, и это предотвращает ожидаемую инициализацию? Вы можете упростить свой код в публикуемый пример, который все еще помечает ошибку valgrind?

альтернативно, возможно, ваш компилятор на самом деле не инициализирует значение POD структуры.

в любом случае, вероятно, самое простое решение-написать конструктор(ы) по мере необходимости для структуры/подразделов.

вам нужно инициализировать все элементы, которые у вас есть в вашей структуре, например:

struct MyStruct {
  private:
    int someInt_;
    float someFloat_;

  public:
    MyStruct(): someInt_(0), someFloat_(1.0) {} // Initializer list will set appropriate values

};

Я пишу тестовый код:

#include <string>
#include <iostream>
#include <stdio.h>

using namespace std;

struct sc {
    int x;
    string y;
    int* z;
};

int main(int argc, char** argv)
{
   int* r = new int[128];
   for(int i = 0; i < 128; i++ ) {
        r[i] = i+32;
   }
   cout << r[100] << endl;
   delete r;

   sc* a = new sc;
   sc* aa = new sc[2];
   sc* b = new sc();
   sc* ba = new sc[2]();

   cout << "az:" << a->z << endl;
   cout << "bz:" << b->z << endl;
   cout << "a:" << a->x << " y" << a->y << "end" << endl;
   cout << "b:" << b->x << " y" << b->y <<  "end" <<endl;
   cout << "aa:" << aa->x << " y" << aa->y <<  "end" <<endl;
   cout << "ba:" << ba->x << " y" << ba->y <<  "end" <<endl;
}

G++ компиляция и запуск:

./a.out 
132
az:0x2b0000002a
bz:0
a:854191480 yend
b:0 yend
aa:854190968 yend
ba:0 yend

поскольку это структура POD, вы всегда можете установить ее в 0-это может быть самый простой способ инициализации полей (при условии, что это уместно).