Re: a question on execution order
Victor Bazarov <v.Abazarov@comAcast.net> wrote:
Igor Tandetnik wrote:
struct S { int x; }
S f() {
S local = {6789};
tricky t = {local.x};
return local;
};
S global = f();
assert(global.x == 6789);
Again, according to the standard, if NRVO is applied, global and
local are two aliases for the same object. It appears that ~tricky
destrutor has no choice but to set x==1234 inside that object, which
would then trigger the assert.
I guess I missed the part that allowed the local object to be treated
as an alias of the object initialised by the return value from the
function.
The normative wording in the standard is rather hard to parse, but the
example in 12.8/5 is very clear:
<quote>
class Thing {
public:
Thing();
~Thing();
Thing(const Thing&);
Thing operator=(const Thing&);
void fun();
};
Thing f() {
Thing t;
return t;
}
Thing t2 = f();
Here t does not need to be copied when returning from f. The return
value of f may be constructed
directly into the object t2.
</quote>
(If you are interested in how the example follows from normative text, I
can try and explain my reading of the standard on this).
Now if I modify this example somewhat:
class Thing {
public:
int x;
Thing() { x = 1; }
// The rest remains unchanged
};
class tricky {
public:
Thing& ref;
tricky(Thing& r) : ref(r) {}
~tricky() { ref.x = 2; }
};
Thing f() {
Thing t;
tricky tr(t);
return t;
}
Thing t2 = f();
If there is no memory allocated for t, but instead it's constructed
directly into memory occupied by t2, then ~tricky would modify t2 right
before f() returns. I don't see the standard prohibiting this.
Musing on the class/non-class, would then this be better:
S global = { f_original() };
assert(global.x == 6789 };
('f_original' is the one with 'int' return type) ?
There might be workarounds, but that's not the point. The point is that
it appears to be possible for NRVO to change the meaning of the program
even when copy constructors/destructors being elided don't have any side
effects. Personally, I find it quite surprising.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925