Commit 371effd5 authored by scott snyder's avatar scott snyder
Browse files

Add note on argument passing.

parent bf9fd85e
#+MACRO: version 0.1
#+TITLE: Proper ways to pass arguments in C++
#+AUTHOR: Scott Snyder
# Put a frame around examples in LaTeX.
#+LaTeX_HEADER: \usepackage{fancyvrb}
#+LaTeX_HEADER: \RecustomVerbatimEnvironment{verbatim}{Verbatim}{frame=single}
#+LaTeX_HEADER: \usepackage{lineno}
#+LaTeX_HEADER: \linenumbers
#+LaTeX_HEADER: \usepackage{fancyhdr}
#+LaTeX_HEADER: \pagestyle{fancy}
#+LaTeX_HEADER: \rfoot{Version {{{version}}}}
#+LaTeX_HEADER: \lhead{}
This short note is a reminder on the proper way to pass arguments to functions
in ATLAS C++ code.
We basically follow the advice given in Herb Sutter's
[[http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/][Guru-of-the-Week #91]].
In summary:
- Basic types should be passed by value, unless you mean to modify them,
in which case they should be passed by non-const reference. In the latter
case, the intent should be clearly documented. However, prefer returning
a value from a function to modifying a parameter via a reference.
- Things that act like/are typedef'd to basic types, like CLID, are
also best passed by value, as are certain small C++ class types
(generally iterators).
- To pass a class instance to a function that will not be modified,
use a const reference. If the object may be null, use a const pointer.
If the object will be modified, use a non-const reference/pointer
and clearly document the intent.
- To pass ownership of an object to a function, pass a =std::unique_ptr=
by value.
In most cases, =unique_ptr= should be passed by _value_. There are
however a few possible use cases for passing =unique_ptr= by reference:
- The called function may replace the object passed in with another one.
In this case, however, consider returning the new object as the
value of the function.
- The called function may only conditionally take ownership of the
passed object. This is likely to be confusing and error-prone
and should probably be avoided. Consider if a =shared_ptr=
would be better in this case.
There is basically no good case for passing =unique_ptr= as a const reference.
- In cases where you need to interoperate with existing code, or where
C++11 features cannot be used, object ownership may be passed by pointer.
The fact that ownership is transferred should be clearly documented.
_Do not_ pass ownership using references.
Here are a couple examples to illustrate this. For the sake of this
example, assume that class =C= contains a member =Foo* m_owning_pointer=
which the class deletes. (In C++11, it would of course usually be better for
this to be a =unique_ptr=.)
#+BEGIN_EXAMPLE
// --- Best
void C::takesOwnership (std::unique_ptr<Foo> foo)
{
delete m_owning_pointer;
m_owning_pointer = foo.release();
}
// --- Ok if documented.
// Takes ownership of the @c foo pointer.
void C::takesOwnership (Foo* foo)
{
delete m_owning_pointer;
m_owning_pointer = foo;
}
// --- Don't do this!
void C::takesOwnership (Foo& foo)
{
delete m_owning_pointer;
m_owning_pointer = &foo;
}
#+END_EXAMPLE
- To return a simple type or a new instance of a class type, return by value.
- To return a reference to an existing class instance, return by const
reference (if the value cannot be null) or by const pointer (if the value
can be null). If the object is meant to be modified, use non-const
references/pointers.
- If a function returns a newly-allocated object, return a =unique_ptr=
(by value!).
- Again, if required for compatibility reasons, a newly-allocated object
may be returned by pointer. The fact that it is a newly-allocated
object should be clearly documented.
In particular, please remember:
- Do not transfer ownership by reference:
#+BEGIN_EXAMPLE
void doSomething (Track& track)
{
...
delete &track; // NO!
}
Track& newTrack()
{
return *new Track(...); // NO!
}
#+END_EXAMPLE
When a reference argument is seen, the reader should be able to assume
that ownership is not transferred.
- Do not pass =unique_ptr= by const reference.
There's no reason to do this, and it is likely to lead to confusion
about the intent of the code.
These may be subject to compile-time checks in the future.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment