Подтвердить что ты не робот

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

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

На основе того, что я читал, кажется, что:

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

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

myStruct = new MyStruct();

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

4b9b3361

Ответ 1

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

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

struct C
{
    int x; 
    int y;
};

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

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

C  c = C();      // Zero initialize using default constructor
C  c{};          // Latest versions accept this syntax.
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).

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

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

C c(); // Unfortunately this is not a variable declaration.
C c{}; // This syntax was added to overcome this confusion.

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

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

Ответ 2

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

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

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

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

Ответ 3

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

struct MyStruct {
  private:
    int someInt_;
    float someFloat_;

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

};

Ответ 4

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

#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

Ответ 5

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