Stupid scope destruction question
monarch_dodra
monarchdodra at gmail.com
Mon Sep 24 12:46:45 PDT 2012
On Monday, 24 September 2012 at 17:49:22 UTC, Ali Çehreli wrote:
> On 09/24/2012 12:49 AM, monarch_dodra wrote:
> > On Monday, 24 September 2012 at 07:25:28 UTC, Denis
> Shelomovskij wrote:
> >> 20.09.2012 15:35, monarch_dodra пишет:
> >>>
> >>> AFAIK, if the rules are the same in C++ (which they
> probably are), then:
> >>> "Any object constructed during argument passing will remain
> valid for
> >>> the duration of the call. It will go out of scope once the
> function has
> >>> finished returning, and after the return value has itself
> gone out of
> >>> scope and been destroyed."
>
> That sounds like you are saying that the temporary S() is
> destroyed after 'r' below:
>
> // C++ code
> R r = foo(S());
>
> > How is my statement incorrect? The "function call" itself
> doesn't change
> > anything sure, since it is more generally a "full
> expression": The
> > return value itself is created *during* that full expression,
> but after
> > the creation of the arguments. Last in, first out, it is
> destroyed
> > before the passed in arguments.
>
> That is not correct. The temporary S() is destroyed at the end
> of the assignment expression (at the semicolon), while 'r' will
> live until the end of the current scope.
>
> Ali
Ah... but see, "s" is *not* the temporary returned value.
It is a normal stack variable to which the the return value is
copied. Also, as I said, in this situation, the compiler will
elide the return completely by constructing the returned value
directly into s, so you won't see the destroyer.
Try this though:
--------
void main()
{
S s;
foo(S(1));
}
--------
D: C++
---- ----
C0 C:0
C1 C:1
foo(S) foo(S)
C2 C:2
D~1 D~:2
D~2 D~:1
D~0 D~:0
---- ----
As you can see, three destructors. It would appear that D,
contrary to C++, actually destroys the return value before the
passed in arguments. Interesting. A valid behavior like any other
I guess, but doesn't change much. I'll admit I was wrong
regarding that (regarding D), but it stays right for C++ :p
Not your example you ask? HERE is the *money* example:
--------
void main()
{
S s;
s = foo(S(1));
}
--------
D: C++
---- ----
C0 C:0
C1 C:1
foo(S) foo(S)
C2 C:2
D~1 D~:2
D~0 D~:1
D~2 D~:2
---- ----
Again 3 destroyers. Again, C++, again works as I said.
Regarding D, WTF is D~0 ? That is D's "return value move" into
action! First time I observe it myself! Exciting!
* First, the passed in argument is destroyed: D~1.
* Then it gets interesting:
* D first calls a destroyer on s (but doesn't actually remove it
from the stack): D~0.
* Then D does a memcpy from the returned value, onto s (the move).
* Finally, the actual return value is then removed from the
stack, but no destructor ever called on it.
* Finally, at the end of the program, s is destroyed (D~2).
Neat-o!
More information about the Digitalmars-d-learn
mailing list