views:

118

answers:

4

Hey!

Let's say i have 2 classes:

class Class1
{
public:
  std::vector<CustomClass3*> mVec;
public:
  Class1();
  ~Class1()
  {
    //iterate over all the members of the vector and delete the objects
  }
};

class InitializerClass2
{
private:
  Class1 * mPtrToClass1;
public:
  InitializerClass2();
  void Initialize()
  {
    mPtrToClass1->mVec.push_back(new CustomClass3(bla bla parameters));
  }
};

Will this work? Or the memory allocated in the InitializerClass2::Initialize() method might get corrupted after the method terminates?

Thanks!

+1  A: 

It should work (provided mPtrClass1 is a valid pointer of course).

jpalecek
+1  A: 

May I suggest that in your InitializerClass2 that you change the constructor to the following:

InitializerClass2() : mPtrToClass1(NULL){}
~InitializerClass2(){
    if( mPtrToClass1 != NULL) delete mPtrToClass1;
}

void Initialize(){
    if( mPtrToClass1 == NULL){
        mPtrToClass1 = new InitializerClass1();
    }

    mPtrToClass1->mVec.push_back(new CustomClass3(bla bla parameters) );
}

if you're not going to use RAII, so that you don't get issues with checking the destructor.

As to your question, see where I added in the new operator. YOu're not initializing your variable.

wheaties
Your suggestions are valid. However, the mPtrToClass1 initialization should probably happen in the constructor. The poster might be assuming that it does. Creating a new instance of Class1 in initialize is a little strange. Calling Initialize repeatedly will cause a memory leak.
Anatoly Fayngelerin
The NULL check on mPtrToClass1 is unnecessary. delete is specified to do that.
Steve Fallows
actually yes, the constructors are all ok, i just did not write it here, because i'm interested just in the Initialize() method where i allocate the memory and push it into the vector of mPtrToClass1.
Anubis9
@Steve Fallows - depends on which compiler you're using.
wheaties
@wheaties - you mean a standards compliant one or not? :)
Steve Fallows
+2  A: 

In short this will work fine.

The memory being allocated in Initialize is on the heap. This means that changes in the stack do not affect the contents of this memory.

Anatoly Fayngelerin
so, this:void Initialize(){ mPtrToClass1->mVec.push_back(new CustomClass3(bla bla parameters));}is different from this:void Initialize(){ CustomClass3* tempPtr= new CustomClass3(bla bla); mPtrToClass1->mVec.push_back(tempPtr));}Because in the second case, i think, "tempPtr" get's deleted after method's termination and the memory might get overwritten. Right?
Anubis9
@anubis9: wrong. In c++ there is no automated lifetime management of raw pointers. In neither of the cases the object will be deleted when the method exits.
David Rodríguez - dribeas
Oh, i see. Thank you!
Anubis9
+2  A: 

One issue I see with Class1 is that it is not copy safe yet the copy and assignment constructors have not been suppressed.

This can cause a problem because the destructor of Class1 is noted as freeing the memory for all items in mVec. Using the implicit operator this means that you'd end up with 2 instances of Class1 pointing to the same CustomClass3 instances and the second destructor would be double deleting memory. For example

Class c1;
c1.mVec.push_back(new CustomClass3(...));
Class c2 = c1;

In this case the second destructor to run (c1) will be freeing an already deleted CustomClass3 instance. You should disable copy construction and assignment for Class1 to prevent this

class Class1 { 
  ...
private:
  Class1(const Class1&);
  Class1& operator=(const Class1&);
};
JaredPar
Oh, forgot about that, thx! I'll make the changes.
Anubis9