Consider this program:
#include <stdio.h>
struct S {
S() { print(); }
void print() { printf("%p\n", (void *) this); }
};
S f() { return {}; }
int main() { f().print(); }
As far as I can tell, there is exactly one S
object constructed here. There is no copy elision taking place: there is no copy to be elided in the first place, and indeed, if I explicitly delete the copy and/or move constructor, compilers continue to accept the program.
However, I see two different pointer values printed. This happens because my platform's ABI returns trivially copyable types such as this one in CPU registers, so there is no way with that ABI of avoiding a copy. clang preserves this behaviour even when optimising away the function call altogether. If I give S
a non-trivial copy constructor, even if it's inaccessible, then I do see the same value printed twice.
The initial call to print()
happens during construction, which is before the start of the object's lifetime, but using this
inside a constructor is normally valid so long as it isn't used in a way that requires the construction to have finished -- no casting to a derived class, for instance -- and as far as I know, printing or storing its value doesn't require the construction to have finished.
Does the standard allow this program to print two different pointer values?
Note: I'm aware that the standard allows this program to print two different representations of the same pointer value, and technically, I haven't ruled that out. I could create a different program that avoids comparing pointer representations, but it would be more difficult to understand, so I would like to avoid that if possible.
-fno-elide-constructors
g++ still gives different results but the addresses are the same in clang – Anachronisticb
andd
do look alike. :) – Iyeyasuthis
's address? – Composer