There are two main considerations. One is the expense of copying the passed object and the second is the assumptions that the compiler can make when the object is a a local object.
E.g. In the first form, in the body of f
it cannot be assumed that that a
and b
don't reference to same object so after any write to b
, the value of a
must be re-read just in case. In the second form a
cannot be change via a write to b
as it is local to the function so these re-reads are unnecessary.
void f(const Obj& a, Obj& b)
{
// a and b could reference the same object
}
void f(Obj a, Obj& b)
{
// a is local, b cannot be a reference to a
}
E.g.: In the first example the compiler may be able to assume that the value of a local object doesn't change when an unrelated call is made. Without information about h
the compiler may not know whether that function changes an object that it has a reference to (via a reference parameter) isn't changed by h
. For example, that object might be part of a global state which is modified by h
.
void g(const Obj& a)
{
// ...
h(); // the value of a might change
// ...
}
void g(Obj a)
{
// ...
h(); // the value of a is unlikely to change
// ...
}
Unfortunately this example isn't cast iron. It is possible to write a class that, say, adds a pointer to itself to a global state object in its constructor so even a local object of class type might be altered by a global function call. Despite this, there are still potentially more opportunities for valid optimizations for local objects as they can't be aliased directly by references passed in or other pre-existing objects.
Passing a parameter by const
reference should be chosen where the semantics of references are actually required, or as a performance improvement only if the cost of potential aliasing would be outweighed by the expense of copying the parameter.