oh-mms
oh-mms

Reputation: 21

What is the difference between these initializations?

I used to know that uninitialized member variables are initialized with a garbage value.

But, If there is a pointer variable uninitialized in a class, all of the uninitialized member variables are initialized with zero.

I think the pointer variable is just pointing an instance in heap memory.

Why are other variables changed?

I don't know what the difference is between these initializations.

Below is the code I tried for step by step.

#include <iostream>

using namespace std;

class Test {
private:
    int val1;
    int val2;

public:
    void PrintValue() {
        cout << "val1: " << val1 << endl;
        cout << "val2: " << val1 << endl;
    }
};

int main() {
    Test a;
    a.PrintValue();
}

then, the result is

val1: -858993460
val2: -858993460

In this code, I added 'int* ptr = new int' like below.

#include <iostream>

using namespace std;

class Test {
private:
    int val1;
    int val2;
    int* ptr = new int;

public:
    void PrintValue() {
        cout << "val1: " << val1 << endl;
        cout << "val2: " << val1 << endl;
    }
};

int main() {
    Test a;
    a.PrintValue();
}

The result is like this.

val1: 0
val2: 0

Why does this happen?

I'm using VS community 2019 and build tools v142.

Upvotes: 2

Views: 91

Answers (2)

Jay
Jay

Reputation: 2946

The difference here is that adding the int* ptr = new int changes your class under the hood from a POD(plain old data) class to a non-POD class.
If you try with your first example

class Test {
public:
    int val1;
    int val2;

    void PrintValue() {
        cout << "val1: " << val1 << endl;
        cout << "val2: " << val1 << endl;
    }
};

int main() {

    Test t;
    cout << t.val1 << endl;
}

Then you will get a compiler error because it knows you are trying to access uninitialized variables.

However, when you add the more complex int* ptr = new int then your class becomes non-POD and so the compiler creates a default constructor for you, which will initialize your variables for you.
Therefore

class Test {
public:
    int val1;
    int val2;
    int* ptr = new int;
    void PrintValue() {
        cout << "val1: " << val1 << endl;
        cout << "val2: " << val1 << endl;
    }
};

int main() {

    Test t;
    cout << t.val1 << endl;
}

This becomes legal and will now compile (although as other answers pointed out, while the output of this may look cleaner, and it won't throw an error, accessing these default initialed variables may still be UB)

more info on POD

Upvotes: 1

songyuanyao
songyuanyao

Reputation: 172884

Nothing changed. As the effect of default initialization, the data member val1 and val2 will be initialized to indeterminate value; any use of them leads to UB, anything is possible.

otherwise, nothing is done: the objects with automatic storage duration (and their subobjects) are initialized to indeterminate values.

Default initialization of non-class variables with automatic and dynamic storage duration produces objects with indeterminate values

Upvotes: 5

Related Questions