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

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

Исходя из того, что я прочитал, кажется, что:

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

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

myStruct = new MyStruct();

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

7 ответов

Решение

В 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 = 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();

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

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

#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

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

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

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

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

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

struct MyStruct {
  private:
    int someInt_;
    float someFloat_;

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

};

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

          You can declare and initalise structure in C++ this way also:::
    
    struct person{
        int a,h;
     
        person(int a1,int h1): a(a1),h(h1){
            
        }// overriden methods

        person():a(0),h(0){
            
        }// by default
    };

   struct person p; 
   --> This creates from by default Person Age: 0 height: 0

   struct person p = person(3,33);  
    --> This creates from overriden methods Person Age: 3 height: 33
     

     

Мне кажется, это самый простой способ. Члены структуры могут быть инициализированы с помощью фигурных скобок '{}'. Например, ниже приведена допустимая инициализация.

struct Point 
{ 
   int x, y; 
};  

int main() 
{ 
   // A valid initialization. member x gets value 0 and y 
   // gets value 1.  The order of declaration is followed. 
   struct Point p1 = {0, 1};  
}

Есть хорошая информация о структурах в C++ - https://www.geeksforgeeks.org/structures-in-cpp/

Другие вопросы по тегам