Can NRVO be turned off in debug builds?

155 views Asked by At

In the program as follows

#include <iostream>

struct A 
{ 
    A() { std::cout << "0"; }
    A( const A & ) { std::cout << "1"; }
    A( A && ) noexcept { std::cout << "2"; }
};

A foo()
{
    A res;
    return res;
}
 
int main()
{
    const A a = foo();
    (void)a;
}

I expected named returned value optimization take place in foo(), so neither copy nor move constructor will be called. And indeed gcc and clang print “0”.

But Visual Studio 2019 in Debug configuration prints “02”. Is it allowed for the compiler to avoid NRVO in debug builds?

2

There are 2 answers

1
SergeyA On BEST ANSWER

Since mandatory copy elision doesn't apply here, yes, compiler is not obligated to optimize away a move in any builds, be it debug or optimized ones.

It is allowed, but not required.

0
the_bugger On

It's unnamed returned value optimization(URVO) that is mandatory since C++17, not NRVO. Nevertheless in practice, most mainstream compilers employ NRVO because of the fact that copy elision is even better than a move operation, since it just constructs the object in place. Now even if I try to force MSVS 2022 in debug mode by calling a function like foo() in your code and adding more complex statements inside, it doesn't call copy/move ctor.