When designing an interface for passing objects which are meant to be stored for later use and which should not be 'null', I am always a bit uncertain if the argument should be passed by reference or as a pointer.
This is an example of what I mean:
class Foo
{
private:
Bar* m_bar;
public:
Foo() : m_bar(nullptr)
{
}
void Register(Bar& bar)
{
m_bar = &bar;
m_bar->Registered();
}
// -- OR --
void Register(Bar* const bar)
{
if (bar == nullptr)
{
// Error!
}
m_bar = bar;
m_bar->Registered();
}
// Some method makes use of the stored pointer later
void DoSomething()
{
if (m_bar == nullptr)
{
// Error!
}
m_bar->DoOtherThing();
}
};
My thoughts on this are:
- The passed in reference may go out of scope before
DoSomething
gets called, but that may happen with the pointed to object as well. - Using the pass-by-non-const-reference version gets rid of duplicating the check for null and tells the caller that it is not possible to register 'nothing'.
- It would be better to pass a reference in the constructor of
Foo
as it is required byDoSomething
, but sometimes it this is not an option. - It would be better to pass a reference to
DoSomething
directly, but again, this is not always possible.
So if I need that kind of separate setter/register method, would it be clearer to use a reference or a pointer?
PS I know there is are two very similar questions Storing a pass-by-reference parameter as a pointer - Bad practice? and Reference vs dereference pointers in arguments C++/C, but I think they both are concerned with slightly different problems. The former deals mostly with the (ab)use of const
and the latter does not say anything about storing a pointer. There may be another question/answer out there, if so, please just mark this a duplicate then!
m_bar
aBar
instead of aBar *
and your problem disappears. Also a reference is preferable ifnullptr
is not a viable argument.Bar
is an abstract class, this won't work.std::unique_ptr<Bar>
. Besides accepting anullptr
it clearly documents how the interface is to be used.