I think it should, because it's important for correctness. However, I'm surprised to see Clang's output. Consider the code below:
#include <iostream>
struct S
{
int i;
S(int i) : i(i) {}
S(S&&)
{
std::cout << "S(S&&)\n";
}
S(S const&) = delete;
};
S f()
{
S s{42};
std::cout << &s << "\n";
return s;
}
int main()
{
S s{f()};
std::cout << &s << "\n";
std::cout << s.i << "\n";
}
We defined a move ctor for S
to check if S(S&&)
is called, if not, NRVO is applied.
The result we see from GCC is:
0x7ffc3ed7b5ac
0x7ffc3ed7b5ac
42
NRVO is applied and they take the same address, which is expected.
However, Clang's output:
0x7fff908bbcc8
0x7fff908bbcf8
42
NRVO is applied but the addresses differ.
In case you wonder why having the same address is important - it's because some object may do some registration with its address at construction, and if the object is moved, it should be notified (e.g. via move-ctor).
Having NRVO applied but with different memory address thus makes it ill-formed. It's a clear violation of the contract - no custom move/copy ctor is called, how could the compiler "copy" the data of S to a different place?
Is this a bug in Clang?
If we add a destructor to S
, e.g.
~S() {}
This time, Clang outputs the same address.