Question

I am learning C++ as a hobby and am wrestling with using "new" to dynamically create a class object. I have read that dynamically created classes do not lose scope, but that does not seem to work for my simple example.

When executed, the value of 'testValue1' is set to 555 in the constructor and printed. When the control is returned to main, 'testvalue' is unfortunately set to 0 (or not defined--not sure). I can set the value inside of main and the value is properly maintained inside of main as well as in a for loop.

The problem: I don't understand why the initialized value of 555 is not maintained when control is returned to main. I know I am doing something wrong or not understanding scope for dynamically assigned class object properly...any assistance is appreciated. Here is the sample code:

//main.cpp
#include <iostream>  
using namespace std;

class generalVars
{
    private:    
    public:
    //data attributes
    int testValue1; 

    //constructor
    generalVars()
    {
        cout << "I am in general vars constructor" << endl;
        int testValue1= 555;
        cout << "testValue1 has been set " << testValue1 << endl;
    }

    ~generalVars(void)
    {
        cout << "I am in general vars destructor" << endl;
    };
};


int main(int argc, char *argv[])
{
    cout << "I am in Main" << endl;
    generalVars* myGeneralVars = new generalVars; //create on heap

    cout << "Main1 testvalue1 = " << myGeneralVars->testValue1 << endl;

    myGeneralVars->testValue1 = 777;
    cout << "Main2 testvalue1 = " << myGeneralVars->testValue1 << endl;

    for (int i=0; i<= 3; i++) 
    {
        cout << "Inside while loop..." << endl;
        cout << "Main3 " << i << " testvalue1 = " << myGeneralVars->testValue1 << endl;
    }
    delete myGeneralVars; //delete from heap
    return 0;
}
Was it helpful?

Solution

This statement:

int testValue1= 555;

declares a local variable, distinct from the data member of the same name.

So it doesn't change the value of the member.

Instead, do e.g.

testValue1= 555;

Or use the constructor's memory initializer list, like this:

generalVars()
    : testValue1( 555 )
{
    cout << "I am in general vars constructor" << endl;
    cout << "testValue1 has been set " << testValue1 << endl;
}

OTHER TIPS

You defined another variable in generalVars constructor and init value to 555, to init member testValue1, you don't need to define it again in constructor.

update

generalVars()
{
    cout << "I am in general vars constructor" << endl;
    int testValue1= 555; // this defines another testValue1 variable. it's different from member testValue1
    cout << "testValue1 has been set " << testValue1 << endl;
}

to

generalVars()
{
    cout << "I am in general vars constructor" << endl;
    testValue1= 555;  // Note, removed int 
    cout << "testValue1 has been set " << testValue1 << endl;
}

Two things are going on:

1) you re-declare testValue1 here by putting int in front:

generalVars()
{
    cout << "I am in general vars constructor" << endl;
    int testValue1= 555; //right here!
    cout << "testValue1 has been set " << testValue1 << endl;
}

This hides the class's own instance of testValue1 with a new unique variable by the same name. You can reference both like so:

generalVars()
{
    cout << "I am in general vars constructor" << endl;
    int testValue1= 555; //note, still has int
    cout << "testValue1 has been set " << testValue1 << endl;
    cout << "this->testValue1 has not been set and is " << this->testValue1 << endl;
    this->testValue1 = 555; //note, this->
    cout << "this->testValue1 has been set " << this->testValue1<< endl;
}

Or you could avoid the name clash and refer to it normally:

generalVars()
{
    cout << "I am in general vars constructor" << endl;
    testValue1= 555; //note, no int.  This is identical to this->testValue1
    cout << "testValue1 has been set " << testValue1 << endl;
}

Next is not really an issue, but should be noted:

You do not need to heap allocate things with new in C++ most of the time. You should prefer stack allocated objects

generalVars myObject;

instead of:

generalVars *myObject = new generalVars();
...
delete myObject;

Or, in cases where you do want to create a heap allocated object:

auto myObject  = std::make_unique<generalVars>();

Or, if you need multiple handles:

auto myObject  = std::make_shared<generalVars>();

The unique_ptr and shared_ptr examples do not require explicit deletion. The heap allocation will be deleted when the pointer object goes out of scope. This especially helps with exception safety.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top