Правильный способ инициализации структур 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/