I'm trying to understand how pointers within objects behave when these objects are returned from functions, particularly in relation to copy elision and temporary object creation in C++ standards before and after C++17. Below is my code example:
struct A {
void* p;
A() : p(this) {}
A(const A&); // Disable trivial copyability
};
A f() {
A x;
return x;
}
int main() {
A a; // OK: a.p points to a
A b = f(); // Concern: b.p could be dangling and point to the x inside f
A c = A(); // (until C++17) Concern: c.p could be dangling and point to a temporary
// (since C++17) OK: c.p points to c; no temporary is involved
}
Specifically, my concerns are:
In A b = f();, is it correct that b.p could be a dangling pointer pointing to x inside f(), depending on whether the compiler applies RVO before C++17?
For A c = A();, I understand that in C++17, c.p points directly to c with no temporary involved. But prior to C++17, could c.p be a dangling pointer if a temporary object is created and then destroyed?
I would appreciate any clarification or insights into how these scenarios are handled in different C++ standards.
P.S. I specifically meant C++11 and C++14 as this code won't compile in C++03
When a copy is elided, it means that the the source and destination objects are the same object. There is no copy; that's the whole point.
No. Because
A's copy constructor isn't implemented, the only way for it to possibly be returned fromfis via NRVO, in which casebandxare the same object. Behind the scenesmainpasses a pointer tofinto whichfinitializes its return object. When (N)RVO is applied,mainandfsimply both use that storage directly asbandx, respectively, instead offcopyingxinto the return value and thenmaincopying from the return value tob.No. Because
A's copy constructor isn't implemented there's no way for a temporary to be copied toc. That means that the only way the program could possibly compile is if the copy is elided andcis directly initialized.Note that I don't think it's a good idea to rely on this behavior. It would be very easy for someone to get a random link error (because NRVO didn't get applied in some situation) and change the copy constructor to
A(const A&) {}to "fix" the problem, which could easily lead to dangling pointers.