Aussie AI
Pass function parameters by reference
-
Book Excerpt from "Generative AI in C++"
-
by David Spuler, Ph.D.
Pass function parameters by reference
Passing objects or large parameters by value is an inefficiency.
The C++ language provides a very convenient method of achieving pass-by-reference, by
simply using &
in the parameter declaration.
One method of improving efficiency is to pass objects to functions as reference
parameters.
Behind the scenes, pass-by-reference is like passing a single pointer as the parameter. This avoids not only the cost of copying a large object onto the stack, but also the cost of the copy constructor and destructor for the object within the function (i.e. the parameter is a separate object when passed by value).
A function parameter can be changed to use pass-by-reference parameters only if it does not
change the object. Fortunately, modifications to parameters can be detected simply by
qualifying the parameter declaration with const
, thus forcing the compiler to warn
about any modifications to the object within the function. An example of the use of
reference parameters in the definition of a Complex
object is shown below:
class Complex { double r, i; public: Complex & operator += (const Complex & c); // c is passed by reference for efficiency // The return type is also a reference }; Complex & Complex::operator += (const Complex & c) { r += c.r; // add to both data fields i += c.i; return *this; // return reference to updated object }
Const reference parameters.
Passing the argument by reference improves efficiency by avoiding big objects.
Note that the parameter is declared “const
” as well as “&
” indicating a reference.
This “const&
” pattern is the common C++ idiom for simulating a non-modified pass-by-value object
send into a function as a faster reference type.
Returning References.
This code also has a second optimization: reference return types.
Making the return value a
reference is also efficient, because the return
statement does not invoke the copy constructor. Note
that a returned reference is necessary only if the user of the Complex
class uses complicated expressions such as x+=y+=z
. If such expressions are not required, efficiency can
be improved by making the return type void
.
Objects Only.
The use of references is best limited to class objects, and also to structures and unions.
Arrays are already passed by reference in C++ and hence there is no need to
change them.
The use of references for scalar types (integers, float
, double
, and pointers) is unlikely to
give much improvement, if any, and might even be slower for some.
Pitfall: Temporary Objects.
Another disadvantage of using reference parameters for scalar types like “int
” is the inefficiency
caused if a constant value is passed as an argument (i.e. a number not a variable). Paradoxically,
passing a constant argument to a reference parameter is not an error in C++, but instead a
new temporary object with this type is created automatically by the compiler and its address passed.
Implicit “this” object.
Note that the object to which a member function is applied is already passed by reference in a certain sense,
because it is using the implicit “this
” parameter. Hence, the simple types of member function calls
are already efficiently using a hidden type of pass-by-reference of the object itself.
Consider this code:
int MyClass::fn() // member function { return x; }
It is not faster with a non-member friend
function call that uses an explicit reference parameter.
This code will not be more efficient (and is probably less efficient):
int fn(MyClass & object) // friend function { return object.x; }
• Next: • Up: Table of Contents |
The new AI programming book by Aussie AI co-founders:
Get your copy from Amazon: Generative AI in C++ |