wjmolina
wjmolina

Reputation: 2675

Constructor Call Within Different Constructor Yields Erroneous Data

The following is the smallest program that replicates my problem:

#include <iostream>

using namespace std;

class Test
{
public:
    Test()
    {
        _a = 0;
    }
    Test(int t)
    {
        Test();
        _b = t;
    }
    void Display()
    {
        cout << _a << ' ' << _b << endl;
    }
private:
    int _a;
    int _b;
};

int main()
{
    Test test(10);
    test.Display(); // 70 10

    return 0;
}

When I do this, _a is initialized with garbage. Why does this happen? Is there a problem when a constructor is invoked from within another?

Upvotes: 3

Views: 76

Answers (1)

templatetypedef
templatetypedef

Reputation: 372814

The issue here is in this code:

Test(int t)
{
    Test();
    _b = t;
}

This does not call the default Test constructor, then set _b = t. Instead, it creates a temporary object of type Test using the default constructor, ignores that temporary object, then sets _b = t. Consequently, the default constructor won't run for the receiver object, so _a will remain uninitialized.

To fix this, in C++11, you can write

Test(int t) : Test() {
    _b = t;
}

which does call the default constructor, or (in C++03) you can factor out the initialization code from the default constructor into a helper member function that you call from both the default and parameterized constructor:

Test() {
    defaultInit();
}
Test(int t) {
    defaultInit();
    _b = t;
}

Or, if you have a C++11 compiler, just eliminate the default constructor by using default initializers, like this:

class Test
{
public:
    Test() = default;
    Test(int t)
    {
        _b = t;
    }
    void Display()
    {
        cout << _a << ' '<< _b << endl;
    }
private:
    int _a = 0;
    int _b;
};

Hope this helps!

Upvotes: 10

Related Questions