Why are RVO and NRVO not mandatory by standard?

Why is the optimization of RVO and NRVO not required (when applicable) by the standard? for example, there is a very common case when a function creates an object and returns it as a result. The copy / move constructors are usually removed due to RVO / NRVO, but they still need to be determined, which is somewhat confusing. If RVO / NRVO was standard, copy / move constructors are no longer needed in this case.

+7
c ++ copy-elision
source share
1 answer

Coding is not required by the standard, because all implementations will require all implementations.

Just take a look at the case of optimization-return vs named-return-value-optimization. Just change this:

std::string Func() { return std::string("foo"); } 

In this functionally identical code:

 std::string Func() { std::string named("foo"); return named; } 

The latter requires much more from the compiler than the former. Different compilers support NRVO in different circumstances. Of course, most of them support this in this trivial case, but there are many different cases. And there are some cases where compilers simply say โ€œspinโ€ and donโ€™t do optimization at all.

Your path will require one of the following:

  • Ensure forced copying in all applicable cases, no matter how difficult it is to implement compilers. Therefore, now every compiler author must deal with such cases:

     std::string Func(bool b) { if(b) { std::string named("foo"); return named; } else { std::string named("bar"); return named; } } 

    Many compilers do not handle NRVO in these cases. And this is a simple case; they can get a lot harder than that.

  • Go through each compiler and find a common subset of cases where a copy of elision is always used, and then specify them in the standard as requirements. It is completely ridiculous; You will be standardized based on implementation details. This is never good.

Please note that C ++ 17 may receive a copy protection guarantee in a specific case. Namely, elite is required to copy / move at any time when a temporary value is used to initialize an object of the same type. This allows you to return a fixed object from a function.

+2
source share

All Articles