vkn
vkn

Reputation: 301

Defining a reference as a function call - what are the benefits?

I've come across code that looks like this:

std::vector<foo> someFunction(Args args)
{
    std::vector<foo> value;
    /*...*/
    return value;
}
std::vector<foo> someOtherFunction(OtherArgs args)
{
    std::vector<foo> value;
    /*...*/
    return value;
}

const auto bar = someFunction(args);
const auto& rBar = someOtherFunction(otherArgs);

I am wondering if there is any significant difference to these being references or not. I have tested the performance of these two using a timer and didn't find any significant difference in result, and the two variables appear to behave in the exact same way, at least on the surface.

Is one of these preferable, and if so, why? Consistency arguments aside.

Apologies if the title is unclear, I really wasn't sure what to call this.

Further digging

I checked the disassembly of these two lines in Visual Studio 2015 (MSVC v140) and found this:

non-reference:

mov    edx,20h
lea    rcx,[vec]
call   std::vector<int, std::allocator<int> >::__autoclassinit2
lea    rcx,[vec]
call   someFunction
nop

reference:

lea    rcx[rbp+88h]
call   someFunction
nop
lea    rax,[rbp+88h]
mov    qword ptr [rVec],rax

Unfortunately, my assembly-fu is nowhere near good enough to appreciate exactly what's going on here.

Upvotes: 1

Views: 67

Answers (2)

eerorika
eerorika

Reputation: 238401

I am wondering if there is any significant difference to these being references or not.

No.

The first simply initialises an object variable.

The second initialises a temporary object and binds that object to a reference. The lifetime of the temporary is extended to the lifetime of the reference (usually temporaries exist only until the end of the full expression).

In the end, once the program is optimised, there is no difference whatsoever.

Is one of these preferable

Yes. const auto bar = someFunction(args);

why?

Because it is simpler and therefore easier to understand. As a bonus, it is less to write as well.

Upvotes: 2

Jarod42
Jarod42

Reputation: 217810

Performance and meaning are similar in your case.

Difference is mostly

  • "readability":

    We know without looking at someFunction declaration that bar has been constructed, and is not a reference/alias. So other unrelated functions cannot change bar but could change rBar indirectly.
    (point goes to bar).

  • behavior with future changes:

    if functions are changed to return (const) reference, bar would make a copy whereas rBar not.
    (point goes to rBar).

Upvotes: 1

Related Questions