Search code examples
c++pointersreturncommand-pattern

Returning a pointer instance variable in C++


I have a command pattern class with a pointer to another object (let's call it Duck). Its subclasses will use Duck, but to control and track when Duck is used (for debugging) I made Duck private and subclasses can only get it through a method getDuck();

class Command
{
    private:
        Duck* target;
    public:
        //Parametrized Constructor
        Command(Duck* _target);
        Duck* getDuck() { return target; }

        ...
};

I recently learned in Effective C++ by Scott Myers the horrors of returning a pointer. I tried just returning the dereferenced version, but that caused a copy of target to be returned. Should I (and is there a way to) simply return a Duck object instead of a pointer to it?


Solution

  • Conceptually, there are two kinds of pointers: owning and non-owning.

    An owning pointer indicates that the holding object/function owns the allocation and is responsible for deleting the object.

    A non-owning pointer is a "borrowed" object; the holding object/function does not own the object and is not responsible for cleaning it up.

    Ideally, this manifests in the C++ type system since C++11 in the following ways:

    • std::unique_ptr<T> is a unique-ownership pointer to a T object. Exactly one object/function can own the allocation.
    • std::shared_ptr<T> is a shared-ownership pointer to a T object. Many objects/functions share ownership of the allocation, and the target object is deleted only when all of them are done with it.
    • T * is a non-owning pointer. This is returned by functions to indicate that the caller does not own the object. The caller is not expected to delete the object; indeed, the caller may not delete it. The caller is expected not to use the pointer once the owning object/function destroys the target object.

    There is nothing inherently wrong with returning a raw pointer, though I would only return a pointer when the function needs to conditionally give access to an object it owns:

    • T *: The function is returning a non-owning handle to an object, but it might not have an object so could return nullptr. T * is "optional, non-owning object handle."
    • T &: The function is returning a non-owning handle to an object, and it will always have such an object to return. T & is "mandatory, non-owning object handle."

    Note that not all standard library facilities will respect these guidelines; indeed not all of them can! new T must return a T * because that's how it's defined to work. These are guidelines that you should follow in your application.