3

I just waste hours on a simple line causing data loss. I have AnotherClass holding a vector of instances of MyClass. This AnotherClass instantiates objects of MyClass the following way:

 AnotherClass::AnotherClass(){            
      MyClass myObject(...);
      myVector.push_back(&myObject);
 }

The address of myObject is afterwards pushed into a vector (with other instances of MyClass), like written in the code. When I start using instances of AnotherClass I notice the values of MyClass were lost (completely random). When I change the code to:

 AnotherClass::AnotherClass(){            
      MyClass* myObject = new MyClass(...);
      myVector.push_back(myObject);
 }

I don't have data loss.

Can somebody be so kind to explain me why the second way of creating objects doesn't lead to a loss of data? (without referencing me to books of 1.000 pages)

2
  • Do you have a particular reason for storing pointers rather than objects? If not, then don't. Commented Nov 27, 2013 at 17:28
  • "I have AnotherClass holding a vector of instances of MyClass." -- No, you don't. Or if you do, it has nothing to do with this code, so I don't know why you mentioned it. Commented Nov 27, 2013 at 17:38

3 Answers 3

9

Simple. The first version creates a local variable on the stack, which gets destroyed automatically when it goes out of scope (at the end of the function)

Your vector just contains a pointer to where the object used to be.

The second version creates an object on the heap, which will live until you eventually delete it.

Sign up to request clarification or add additional context in comments.

Comments

2

The reason is RAII.

In the first snippet you declare an object in the scope of your method/constructor. As soon this scope ends, this is the case when method is finished, your object gets out-of-scope and becomes cleaned for you (this means that its desctructor is called). Your vector now still holds pointers to your already cleaned and thus invalid objects, thats the reason why you get garbage.

In the second snippter, your object are contained on the heap. They wont become cleaned / destroyed unless you call delete myObj;. Thats the reason why they remain valid even after the method has finsihed.

You can solve this on multiple ways:

  • Declare your vector as std::vector<MyClass> (notice, not a pointer type)
  • Keep your second snippet but make sure to delete all elements of your vector once your done
  • Use smart pointers if you dont want to cleanup your objects by your own (e.g std::shared_ptr or std::unique_ptr)

2 Comments

Thank you for the informative answer and alternative solutions. So ` std::vector<MyClass> myVector; ` and ` myVector.push_back(MyClass myObject(...)); ` will ensure the information is kept when I return the instance?
Yes, but the syntax is myVector.push_back(MyClass(...)); . Notice that the accessor methods of std::vector return references. So while a copy is created when you push back objects, code like myVector[2] = foo; will modify the elements inside the vector as myVector[2]returns a reference.
1

The first way allocates a MyClass object on the stack. That object will be deallocated the moment it goes out ofscope, I.e. when the constructor has run its course.

The second way allocates the object in dynamic memory. That object will continue to exist until you call delete on it.

The second way is the way to do it but you should add a destructor to AnotherClass that iterates through the vector and deletes all objects. Otherwise your program will have a memory leak.

1 Comment

Thanks for the warning of the memory leak, that was probably the next problem I was going to encounter ;-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.