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:
- Easy to understand.
- Requires no extra libraries or supporting code.
Cons:
- It requires
Animal
to have a well-behaved copy-constructor. - It can involve a lot of copying if
Animal
is larg and complex, although return value optimization can alleviate that in many situations. - Doesn’t work if you plan on returning sub-classes derived from
Animal
as they will be sliced down to a plainAnimal
, 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:
- Works with object-hierarchies (no object slicing).
- No issues with having to copy large objects.
- No need for
Animal
to define a copy constructor.
Cons:
- Requires either Boost or TR1 libraries, or another smart-pointer implementation.
-
Track all
Animal
allocations inAnimalLister
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:
- Ideal for situations where you need a bunch of
Animal
s for a limited amount of time, and plan to release them all at once. - Easily adaptable to custom memory-pools and releasing all the
Animal
s in a singledelete
. - Works with object-hierarchies (no object slicing).
- No issues with having to copy large objects.
- No need for
Animal
to define a copy constructor. - No need for external libraries.
Cons:
- The implementation as written above is not thread-safe
- Requires extra support code
- Less clear than the previous two schemes
- It’s non-obvious that when the AnimalLister goes out of scope, it’s going to take the Animals with it. You can’t hang on to the Animals any longer than you hang on the AnimalLister.
- Ideal for situations where you need a bunch of