Reputation: 301
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
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
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