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?
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.