What should a C++ getter return

Ferenc Deak picture Ferenc Deak · Nov 20, 2013 · Viewed 29.7k times · Source

What is the best practice for a C++ getter method which is supposed to return a non trivial type, but a member which is of type class, or struct.

  1. Return by value, such as: MyType MyClass::getMyType() { return mMyType; }
  2. Return by const reference: const MyType& MyClass::getMyType() { return mMyType; }
  3. Return by address: MyType* MyClass::getMyType() { return &mMyType; }

where

class MyType { /* ... */ };

class MyClass
{
  private:
     MyType mMyType;
}

I specifically worry about the following usages of this method. Can you please elaborate in details how this might affect copying the object, and the danger of dangling references and wild gone pointers if function() wants to save it for further usage.

MyType* savedPointer;

SomeType function(MyType* pointer) { savedPointer = pointer; };

a. valid for 1. and 2.

{
  MyType t = myClass.getMyType();
  function(&t);
}

// is savedPointer still valid here?

b. valid for 1. and 2.

{
  const MyType& t = myClass.getMyType();
  function(&t);
}

// is savedPointer still valid here?

c. valid for 1. and 2.

{
  MyType& t = myClass.getMyType();
  function(&t);
}

// is savedPointer still valid here?

d. valid for 3.

{
  MyType* t = myClass.getMyType();
  function(t);
}

// is savedPointer still valid here?

where myClass is an object of type MyClass.

Answer

Marcelo Cantos picture Marcelo Cantos · Nov 20, 2013

You can provide both const and non-const versions:

MyType       & MyClass::getMyType()       { return mMyType; }
MyType const & MyClass::getMyType() const { return mMyType; }

I wouldn't provide a pointer version, since that implies that the return value might be the null pointer, which it can never be in this instance.

The real point, however, is that you are basically giving the caller direct access to the internal object. If this is your intent, then you may as well make the data member public. If it isn't, then you will need to work harder to hide the object.

One option is to retain the MyType const & accessor, but provide more indirect means to modify the internal object (setMyType(…) or something more tailored to the semantics that you are trying to express at the level of the containing class).