I expected to see copy elision from Named Return Value Optimization (NRVO) from this test program but its output is "Addresses do not match!" so NRVO didn't happen. Why is this?
// test.cpp
// Compile using:
//      g++ -Wall -std=c++17 -o test test.cpp
#include <string>
#include <iostream>
void *addr = NULL;
class A
{
public:
    int i;
    int j;
#if 0
    ~A() {}
#endif
};
A fn()
{
    A fn_a;
    addr = &fn_a;
    return fn_a;
}
int main()
{
    A a = fn();
    if (addr == &a)
        std::cout << "Addresses match!\n";
    else
        std::cout << "Addresses do not match!\n";
}
Notes:
- If a destructor is defined by enabling the - #ifabove, then the NRVO does happen (and it also happens in some other cases such as defining a virtual method or adding a- std::stringmember).
- No methods have been defined so A is a POD struct, or in more recent terminology a trivial class. I don't see an explicit exclusion for this in the above links. 
- Adding compiler optimisation (to a more complicated example that doesn't just reduce to the empty program!) doesn't make any difference. 
- Looking at the assembly for a second example shows that this even happens when I would expect mandatory Return Value Optimization (RVO), so the NRVO above was not prevented by taking the address of - fn_ain- fn(). Clang, GCC, ICC and MSVC on x86-64 show the same behaviour suggesting this behaviour is intentional and not a bug in a specific compiler.- class A { public: int i; int j; #if 0 ~A() {} #endif }; A fn() { return A(); } int main() { // Where NRVO occurs the call to fn() is preceded on x86-64 by a move // to RDI, otherwise it is followed by a move from RAX. A a = fn(); }
 
     
    