Returning Objects in C++

Depending on your usage, there are a couple of options you could go with here:

  1. 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 plain Animal, losing all the extra data in the sub-class.
  2. 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.
  3. 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:

    • Ideal for situations where you need a bunch of Animals for a limited amount of time, and plan to release them all at once.
    • Easily adaptable to custom memory-pools and releasing all the Animals in a single delete.
    • 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.

Leave a Comment