When returning objects from a class, when is the right time to release the memory?
Example,
class AnimalLister { public: Animal* getNewAnimal() { Animal* animal1 = new Animal(); return animal1; } }
If i create an instance of Animal Lister and get Animal reference from it, then where am i supposed to delete it?
int main() { AnimalLister al; Animal *a1, *a2; a1 = al.getNewAnimal(); a2 = al.getNewAnimal(); }
The problem here is AnimalLister doesnot have a way to track the list of Animals Created, so how do i change the logic of such code to have a way to delete the objects created.
When an object is returned by value from a function, a temporary object is created within the function, which holds the return value. This value is further assigned to another object in the calling function. The syntax for defining a function that returns an object by value is. 1.
An object is an instance of a class. Memory is only allocated when an object is created and not when a class is defined. An object can be returned by a function using the return keyword. A program that demonstrates this is given as follows −
If a method or function returns an object of a class for which there is no public copy constructor, such as ostream class, it must return a reference to an object. Some methods and functions, such as the overloaded assignment operator, can return either an object or a reference to an object.
Depending on your usage, there are a couple of options you could go with here:
Make a copy every time you create an animal:
class AnimalLister { public: Animal getNewAnimal() { return Animal(); } }; int main() { AnimalLister al; Animal a1 = al.getNewAnimal(); Animal a2 = al.getNewAnimal(); }
Pros:
Cons:
Animal
to have a well-behaved copy-constructor.Animal
is larg and complex, although return value optimization can alleviate that in many situations.Animal
as they will be sliced down to a plain Animal
, losing all the extra data in the sub-class. Return a shared_ptr<Animal>
:
class AnimalLister { public: shared_ptr<Animal> getNewAnimal() { return new Animal(); } }; int main() { AnimalLister al; shared_ptr<Animal> a1 = al.getNewAnimal(); shared_ptr<Animal> a2 = al.getNewAnimal(); }
Pros:
Animal
to define a copy constructor.Cons:
Track all Animal
allocations in AnimalLister
class AnimalLister { vector<Animal *> Animals; public: Animal *getNewAnimal() { Animals.push_back(NULL); Animals.back() = new Animal(); return Animals.back(); } ~AnimalLister() { for(vector<Animal *>::iterator iAnimal = Animals.begin(); iAnimal != Animals.end(); ++iAnimal) delete *iAnimal; } }; int main() { AnimalLister al; Animal *a1 = al.getNewAnimal(); Animal *a2 = al.getNewAnimal(); } // All the animals get deleted when al goes out of scope.
Pros:
Animal
s for a limited amount of time, and plan to release them all at once.Animal
s in a single delete
.Animal
to define a copy constructor.Cons:
I advise returning a std::tr1::shared_ptr
(or boost::shared_ptr
, if your C++ implementation does not have TR1) instead of a raw pointer. So, instead of using Animal*
, use std::tr1::shared_ptr<Animal>
instead.
Shared pointers handle reference tracking for you, and delete the object automatically if there are no references left to it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With