2

EDIT: it is NOT a duplicate because this question asks about a compiler's decision in O0.

It is said here that Name Return Value Optimization (NRVO) is an optimization many compiler support. But is it a must or just a nice-to-have optimization?

My situation is, I want to compile with -O0 (i.e. no optimization), for convenience of debugging, but I also want NRVO to be enabled for return statements that return objects (say, a vector). If NRVO is not a must, the compiler probably won't do it in -O0 mode. In this case, should I prefer this code:

std::vector<int> foo() { std::vector<int> v(100000,1); // an object that is really big.. return std::move(v); // explicitly move } 

over this below?

std::vector<int> foo() { std::vector<int> v(100000,1); return v; // copy or move? } 

EDIT: the compiler I am using is GCC6, but I want the code to be compiler-independent.

7
  • Whether the return value gets copied or moved is determined by the function's return type, and its calling context. Nothing that occurs inside the function will have any bearing on that. Commented Aug 14, 2017 at 18:40
  • See stackoverflow.com/a/4986802/576911 Commented Aug 14, 2017 at 18:42
  • 1
    The move is superfluous as the value is already an rvalue (xvalue), and it prohibits copy-elison. So it's just a pessimization overall. Also, don't optimize your unoptimized builds. Commented Aug 14, 2017 at 18:44
  • Alternative duplicate: stackoverflow.com/q/17473753/1896169 Commented Aug 14, 2017 at 19:02
  • 1
    Your only concern should be correctness and selection of the optimal algorithm. Code optimisation is the compiler's concern. Almost always prefer returning by value over returning by r-value reference. Commented Aug 14, 2017 at 21:12

1 Answer 1

6

You should prefer

std::vector<int> foo() { std::vector<int> v(100000,1); return v; // move or NRVO } 

over

std::vector<int> foo() { std::vector<int> v(100000,1); return std::move(v); // move } 

The second snippet prevent NRVO, and in worst case both would move construct.

Sign up to request clarification or add additional context in comments.

12 Comments

why is move construction bad? I thought copy construction is unnecessary and therefore is bad.
In first snippet, you have move constructor or even better NRVO (and in C++17 NRVO guaranty :-) ). In the second snippet, the move call prevent NRVO, so you only have move construct, that is not that bad, but we have better or equal in first snippet with a shorter code.
Not all moves are free. Some moves require additional work to ensure the moved from object is in a valid state. unordered_map for instance, will allocate buckets for a moved from object.
(N)RVO and moving are not the same thing. RVO existed prior to C++11 - it's just a permitted optimization compilers can take. And correct, the copy constructor won't ever be called - at that point v is an rvalue (an xvalue, to be precise) so the constructor that accepts an rvalue (the move constructor) is a better match then the one that doesn't (the copy constructor).
@WeijunZhou: indeed NRVO is never guaranty, RVO is in C++17.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.