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!