Which way to return value works faster in C++?
Clash Royale CLAN TAG#URR8PPP
Which way to return value works faster in C++?
Lets suppose that some function has multiple if
statemens, like in the code below.
Is there any difference in these two ways of returning some default value? Can anyone tell me about pos and cons of these two approaches?
if
First:
CustomClass foo(const Param* par)
if (nullptr == par)
return CustomClass();
if (!check1(par))
return CustomClass();
if (!check2(par))
return CustomClass();
// some code
return CustomClass();
Second:
CustomClass foo(const Param* par)
CustomClass ret;
if (nullptr == par)
return ret;
if (!check1(par))
return ret;
if (!check2(par))
return ret;
// some code
return ret;
Seems it should depends on copiler...
I would be extremely surprised if a compiler would generate different code for this two snippets
– user463035818
Aug 9 at 13:14
Which is faster? Eric Lippert's Performance Rant
– Filburt
Aug 9 at 13:22
Write correct readable code first, then if you have a performance issue you've discovered by profiling that code, optimize that performance issue. If this function is the slowest part of your code it is because of what those check functions do, not because of how you return the variable.
– Retired Ninja
Aug 9 at 14:00
@RetiredNinja: I disagree, almost the whole rant is wrong. When there are multiple solutions to a problem, and someone wants to make a habit to choose the better solution, then it is absolutely valid to put the question about performance. Like this one. If we go back in time, these two solutions could have a performance difference, because compilers weren't smart enough. And it is just a habit to use the better one. Even if it is not the bottleneck, and even if it doesn't make too much difference. Why not choose the better solution (even if it is just 1% better), if it takes nothing to do so?
– geza
Aug 9 at 14:08
2 Answers
2
Both are subjects for compiler optimisation. First one is URVO (unnamed return value optimisation), second - NRVO (named return value optimisation). The C++ standard explicitly allows compilers to elude copying.
[12.8]
When certain criteria are met, an implementation is allowed to
omit the copy/move construction of a class object, even if the
constructor selected for the copy/move operation and/or the destructor
for the object have side effects.
...in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object
(other than a function parameter ...) with the same type (ignoring
cv-qualification) as the function return type, the copy/move operation
can be omitted by constructing the automatic object directly into the
function call’s return object
Modern versions of GCC, Clang, and MSVC would yield equal assembly for both cases even with no optimisations enabled. Here are some examples:
From
C++17
the first option will be a candidate for guaranteed RVO
.– Galik
Aug 9 at 13:55
C++17
RVO
In your URVO example the MSVC is ignoring switches
– P i
Aug 9 at 14:50
The other as well.
– P i
Aug 9 at 14:58
Any sensible compiler should produce the same code for the two functions, because they mean exactly the same thing and the optimiser can deduce this fact relatively easily.
Remember, your source code is not a one-to-one mapping of CPU instructions: it is a description of a program. It is your compiler's job to take this description and produce the best "actual" code that performs the same function, and your compiler is very good at doing so! My point being that the actual compiled code will look almost nothing like either function anyway.
Ultimately, though, whether this is truly the case on your particular platform and using your particular implementation, can only be determined by actually examining the resulting assembly code. If all you care about is performance you could draw the line at benchmarking it.
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Have you tried benchmarking and/or looking at the generated assembly?
– UnholySheep
Aug 9 at 13:14