Channels ▼

Andrew Koenig

Dr. Dobb's Bloggers

Optimization: Calling By Value Or By Reference To Const?

January 11, 2012

Last week, I talked about architectural optimization, which I claimed must be taken into account as part of design. I would like to continue that discussion with another reason for thinking carefully about optimizations rather than making them automatically.

You are probably aware that if we define a function with a parameter that is not a reference, the corresponding argument will be copied when we call the function. For example:

class Thing {
       // …
 };

void foo(Thing t) { /* … */ }

Because the parameter to foo has type Thing, rather than type Thing& (with or without const), calling foo causes the C++ implementation to copy the object that we are passing to foo, thereby making the value of t inside foo distinct from the object that we gave foo as its argument.

Of course, without reading the definition of Thing, we don't know how long it takes to copy an object of that type. For that reason, many programmers are in the habit of defining functions such as Foo to take parameters of type const Thing& rather than of type Thing as an optimization.

I wish such optimizations were always so easy — but of course, if they were, the compiler would be doing it for us and we wouldn't need to worry about it. Alas, there are at least two problems that make it far from automatic to pass arguments to functions by reference. The following example illustrates both of these problems:


void scale(vector<double>& v, const double& x)
 {
       for (size_t i = 0; i != v.size(); ++i)
            v[i] /= x;
 }

This function divides every element in a vector<double> by a given value, x. The author of this function intended to avoid having to copy x each time through the loop by making x a reference to (const) double rather than a double directly. However, suppose we call the function this way:

scale(v, v[0]);

We want to divide each element of v by v[0]. Presumably we have ensured that v has at least one element and that v[0] is not equal to zero. If you look carefully at the code, however, you will see that it sets v[0] equal to v[0]/v[0] (i.e., to 1.0), and then divides every other element of v by 1.0, leaving those elements unchanged. By making x a reference, we have defined x as an alias to what, in this case, turns out to be an element of v itself.

Not only does this use of scale work incorrectly, but a compiler that compiles this code as we've written it will have to copy x each time through the loop anyway — even though we made x a reference to avoid just that possibility. The reason, of course, is that the compiler must cater to the possibility that x is an alias to an element of v, so it cannot store x in an internal register as it might otherwise have done.

If we were to define x as double rather than as const double&, we would be insisting that the program copy x at the beginning of the scale function. This copy would ensure that x would not be an alias for an element of v; so not only would the program now work as expected, but it would do so more quickly.

Defining a function parameter as a reference is a common optimization that avoids copying values that would otherwise have to be copied. However, like all optimizations, it should not be made automatically. Next week I shall discuss some other reasons that this optimization might not be as useful as it appears at first.

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Video