KC3BZU
KC3BZU

Reputation: 1314

Proper way to initialize C++ structs

Our code involves a POD (Plain Old Datastructure) struct (it is a basic c++ struct that has other structs and POD variables in it that needs to get initialized in the beginning.)

Based one what I've read, it seems that:

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

should initialize all the values to zero, as does:

myStruct = new MyStruct();

However, when the struct is initialized in the second way, Valgrind later complains "conditional jump or move depends on uninitialised value(s)" when those variables are used. Is my understanding flawed here, or is Valgrind throwing false positives?

Upvotes: 116

Views: 341819

Answers (7)

Bhanu Mahto
Bhanu Mahto

Reputation: 41

    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
     

     

Upvotes: 1

Michael Klishevich
Michael Klishevich

Reputation: 1854

That seems to me the easiest way. Structure members can be initialized using curly braces ‘{}’. For example, following is a valid initialization.

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};  
}

There is good information about structs in c++ - https://www.geeksforgeeks.org/structures-in-cpp/

Upvotes: 0

Loki Astari
Loki Astari

Reputation: 264601

In C++ classes/structs are identical (in terms of initialization).

A non POD struct may as well have a constructor so it can initialize members.
If your struct is a POD then you can use an initializer.

struct C
{
    int x; 
    int y;
};

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

Alternatively you can use the default constructor.

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).

I believe valgrind is complaining because that is how C++ used to work. (I am not exactly sure when C++ was upgraded with the zero initialization default construction). Your best bet is to add a constructor that initializes the object (structs are allowed constructors).

As a side note:
A lot of beginners try to value 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();

A quick search for the "Most Vexing Parse" will provide a better explanation than I can.

Upvotes: 161

Yadong
Yadong

Reputation: 41

I write some test code:

#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++ compile and run:

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

Upvotes: 4

Scott C Wilson
Scott C Wilson

Reputation: 20026

Since it's a POD struct, you could always memset it to 0 - this might be the easiest way to get the fields initialized (assuming that is appropriate).

Upvotes: 0

Mark B
Mark B

Reputation: 96281

From what you've told us it does appear to be a false positive in valgrind. The new syntax with () should value-initialize the object, assuming it is POD.

Is it possible that some subpart of your struct isn't actually POD and that's preventing the expected initialization? Are you able to simplify your code into a postable example that still flags the valgrind error?

Alternately perhaps your compiler doesn't actually value-initialize POD structures.

In any case probably the simplest solution is to write constructor(s) as needed for the struct/subparts.

Upvotes: 2

ralphtheninja
ralphtheninja

Reputation: 133118

You need to initialize whatever members you have in your struct, e.g.:

struct MyStruct {
  private:
    int someInt_;
    float someFloat_;

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

};

Upvotes: -1

Related Questions