Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Scott Snyder
coding-rules
Commits
371effd5
Commit
371effd5
authored
Aug 09, 2017
by
scott snyder
Browse files
Add note on argument passing.
parent
bf9fd85e
Changes
1
Hide whitespace changes
Inline
Side-by-side
02-arg-passing.org
0 → 100644
View file @
371effd5
#+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.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment