user997112
user997112

Reputation: 30635

Any efficiency benefit to passing primitive types by reference instead of returning by value?

In C++, is there an efficiency benefit in passing primitive types by reference instead of returning by value?

Upvotes: 15

Views: 2616

Answers (3)

mattnewport
mattnewport

Reputation: 14067

In general there won't be any performance benefit and there may well be a performance cost. Consider this code:

void foo(const int& a, const int& b, int& res) {
    res = a + b;
    res *= a;
}

int a = 1, b = 2;
foo(a, b, a);

When a compiler encounters a function like add() it must assume that a and res may alias as in the example call so without global optimizations it will have to generate code that loads a, loads b, then stores the result of a + b to res, then loads a again and performs a multiply, before storing the result back to res.

If instead you'd written your function like this:

int foo(int a, int b) {
    int res = a + b;
    res *= a;
    return res;
}

int a = 1, b = 2;
int c = foo(a, b);

Then the compiler can load a and b into registers (or even pass them directly in registers), do the add and multiply in registers and then return the result (which in many calling conventions can be returned directly in the register it was generated in).

In most cases you actually want the semantics in the pass / return by value version of foo and the aliasing semantics possible in the pass / return by reference version do not really need to be supported. You can end up paying a real performance penalty by using the pass / return by reference version.

Chandler Carruth gave a good talk that touched on this at C++ Now.

Upvotes: 4

Andy Prowl
Andy Prowl

Reputation: 126522

[...] is there an efficiency benefit to passing primitive types by reference instead of returning by value?

Unlikely. First of all, unless you have data from your profiler that give you a reason for doing otherwise, you should not worry about performance issues when designing your program. Choose the simplest design, and the design that best communicates your intent.

Moreover, primitive types are usually cheap to copy, so this is unlikely to be the bottleneck in your application. And since it is the simplest option and the one that makes the interface of the function clearest, you should pass by value.

Just looking at the signature, it is clear that a function such as:

void foo(int);

Will not store a reference to the argument (and consequently, won't run into issues such as dangling references or pointers), will not alter the argument in a way that is visible to the caller, and so on and so on.

None of the above can be deduced from a function signature like:

void f(int&); // May modify the argument! Will it? Who knows...

Or even:

void f(int const&); // May store a reference! Will it? Who knows...

Besides, passing by value may even improve performance by allowing the compiler to perform optimizations that potential aliasing would prevent.

Of course, all of this is under the assumption that you do not actually need to modify the argument inside the function in a way that side-effects on that argument will be visible to the caller after the function returns - or store a reference to that argument.

If that is the case, then you should of course pass by reference and use the appropriate const qualification.

For a broader discussion, also see this Q&A on StackOverflow.

Upvotes: 8

Mark B
Mark B

Reputation: 96291

There may be some obscure architecture where this is the case, but I'm not aware of any where returning builtin types is less performant than passing an out parameter by reference. You can always examine the relevant assembly to compare if you want.

Upvotes: 1

Related Questions