C++ is a very flexible language which allows the programmers to decide how to handle memory allocation and deallocation. With this power, comes the responsibility of deciding and keeping the integrity of resources ownership. Then, with the new C++ 11 and onwards standards, move operations and standard operations are also players.
Now to the point of this post. How to pass things by parameters!? There are many possibilities, and without any kind of guidelines, it is easy to step into the horrible realm of code insanity. The guidelines I’m posting here are ones that I came up while reading discussions on stackoverflow and blogs, and consolidated with my own experience while programming Heldelland. For pointers and references:
- Pass object by reference, if nullptr is not a valid input value;
- Pass a raw pointer to object, if nullptr is a valid input value.
In both cases above, the caller must guarantee data validity while the method or function executes. If it was a constructor, the data must outlive the created object, if it stores the reference/pointer. It is preferred to pass by reference if nullptr is not a valid (non-error) input. This way, propagation of null checks can be avoided:
- Pass unique pointers only if it is possible to happen an ownership change. They should be passed by non-const reference.
The idea behind passing non-const reference is that it makes clear that the method might acquire ownership of the passed address. If no such ownership change is possible, a pass by a raw pointer or reference is preferred. If the unique pointer is not passed by reference, the caller will need to move it, potentially resulting in deallocated object if an error happens before the called method changes ownership:
- Pass shared pointers by constant reference, if no more shared ownership will be added;
- Pass shared pointers by copy, if more shared ownership will be added
Passing shared pointers by copy feels dull, but you can actually move it to its destination, avoiding references counting updates as you store it.