0
int foo() {return 5;}

void bar(int *var) {*var = 5;}

int main()
{
    int lvar;

    lvar = foo();
    bar(&lvar);

    return 0;
}

Is foo or bar the better choice? The benefit of foo, is that can not only be used for changing variable values. But sometimes that is also safer, so a function will not be missused. So what about performance?

Post Self
  • 1,471
  • 2
  • 14
  • 34
  • 3
    Possible duplicate of [Is it a good design to return value by parameter?](http://stackoverflow.com/questions/2452728/is-it-a-good-design-to-return-value-by-parameter) – cantSleepNow Jun 04 '16 at 20:57
  • I would say with compiler optimization in such a easy function would result in the same performance. Its more or less nrvo vs pass by ref and asign. –  Jun 04 '16 at 20:58
  • @Dr.Jones But with more complex code the gap between performance might increase. Does it? – Post Self Jun 04 '16 at 20:59
  • @kim366 Take a look at https://en.wikipedia.org/wiki/Return_value_optimization –  Jun 04 '16 at 21:04
  • 3
    @kim - No, with more complex code, the "complex code" will take most of the time, and any difference in performance will be *less* important. I prefer the version where you can write `const type var = foo();`. – Bo Persson Jun 04 '16 at 21:05
  • @cantSleepNow the possible duplicate is asking for passing a pointer and possibly setting this pointer to null, pass-by-reference via reference is quite different – 463035818_is_not_an_ai Jun 05 '16 at 09:20
  • @tobi303 that's true, however the essence of the question is the same (is it better to return by parameter or by return value) and this is what I was thinking of when I marked it as duplicate – cantSleepNow Jun 05 '16 at 10:32
  • @cantSleepNow actually it would be nice if there was one question asking for return by parameter vs return by value including both possibilities, as the answers are really different for pointer or references. Look at my answer (I am not claiming that it is a perfect one), all what I wrote does not really apply when a pointer is used. – 463035818_is_not_an_ai Jun 05 '16 at 10:43

1 Answers1

0

I would not consider performance as the highest priority when making this decision. Anyhow there is RVO and in general one should not optimize before profiling.

That said, imho the biggest difference is how the calling code looks:

int f = foo();

vs

int x;
bar(x);

When calling a function that returns a value, the intention is perfectly clear at the calling code. Even if you dont know what foo is doing, you dont have to look it up to know it returns an int and takes zero parameters. On the other hand, look at the call to bar. What does it do? Does it change the value of a? The call to bar might be inside a larger block of code and to understand that block of code you have to look up what bar is actually doing. It can be even worse if you mix both:

int foobar(int& x);

I would not suggest you to ever write a function like that, because in the calling code

int x;
int y = foobar(x);

one would expect that x is just a parameter that does not change. On top of that, often the caller is forced to write more code for a simple function call, because he has to declare the return value before calling the function.

Conclusion: Passing a refernce to return values does obfuscate the calling code.

On the other hand, there can be cases where passing a reference is the way to go. A pattern I use from time to time is the following:

struct MooInput {};
struct MooResult{};
void moo(const MooInput& a, MooResult& b);

With the proper names now the caller at least has a chance to write code such that it is clear what is input and what is returned:

MooInput a;
MooOutput b;
void moo(a,b);

PS: The considerations are a bit different if the function takes a parameters, performs some operations on it and returns the result, e.g.

int Boo ( int x) { return x++;}

in that case I often tend to provide also a:

void Coo(int& x) { x++; }

Because the caller might need one of the two versions depending on whether he needs the old value after calling the function or not. If there is only Boo and the caller does not need the old value, he is forced to make a copy (actually an assignment):

int x;
x = Boo(x);

while if there is only Coo and he needs the old value he also needs to make a copy:

int x;
int y = x;
Coo(x);
Community
  • 1
  • 1
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185