Thread overview
[Dlang-study] [lifetime] destructor, difference between C++ and D and rationale
Oct 28, 2015
deadal nix
Oct 29, 2015
deadal nix
Oct 29, 2015
deadal nix
October 28, 2015
Andrei, to quote you :
"[...]at least in v1.0 we're considering having the callER do the increment
and the callEE do the decrement. This is how D currently handles copy
construction and destruction, and it turns out it has a number of
advantages over C++ (where the caller does all the work)."

Can you explain how C++ and D destructor management differs, and what are the rationale behind these differences ?


October 28, 2015
On 10/28/2015 04:39 PM, deadal nix wrote:
> Andrei, to quote you :
> "[...]at least in v1.0 we're considering having the callER do the
> increment and the callEE do the decrement. This is how D currently
> handles copy construction and destruction, and it turns out it has a
> number of advantages over C++ (where the caller does all the work)."
>
> Can you explain how C++ and D destructor management differs, and what
> are the rationale behind these differences ?

Not much of the place here, but in brief in C++ consider the call:

class C { ... };
void fun(C);
int main() { C obj; fun(obj); }

In the call to fun, the callER calls the copy ctor of C, invokes fun, then calls the dtor of C.

In D, the callER calls the copy ctor, but it's the callEE that calls the dtor.


Andrei
_______________________________________________
Dlang-study mailing list
Dlang-study@puremagic.com
http://lists.puremagic.com/cgi-bin/mailman/listinfo/dlang-study

October 28, 2015
I think it is very relevent here as destructor is a very common tool to free resources, as well as one of the most complex to deal with, mostly because of move semantic. I already had in mind to launch that subject before this whole thing started.

Why were things changed that way ?
On Oct 28, 2015 15:33, "Andrei Alexandrescu" <andrei@erdani.com> wrote:

> On 10/28/2015 04:39 PM, deadal nix wrote:
>
>> Andrei, to quote you :
>> "[...]at least in v1.0 we're considering having the callER do the
>> increment and the callEE do the decrement. This is how D currently
>> handles copy construction and destruction, and it turns out it has a
>> number of advantages over C++ (where the caller does all the work)."
>>
>> Can you explain how C++ and D destructor management differs, and what are the rationale behind these differences ?
>>
>
> Not much of the place here, but in brief in C++ consider the call:
>
> class C { ... };
> void fun(C);
> int main() { C obj; fun(obj); }
>
> In the call to fun, the callER calls the copy ctor of C, invokes fun, then calls the dtor of C.
>
> In D, the callER calls the copy ctor, but it's the callEE that calls the dtor.
>
>
> Andrei
> _______________________________________________
> Dlang-study mailing list
> Dlang-study@puremagic.com
> http://lists.puremagic.com/cgi-bin/mailman/listinfo/dlang-study
>


October 29, 2015
On 10/28/2015 08:29 PM, deadal nix wrote:
> I think it is very relevent here as destructor is a very common tool to
> free resources, as well as one of the most complex to deal with, mostly
> because of move semantic. I already had in mind to launch that subject
> before this whole thing started.
>
> Why were things changed that way ?

This would stray further off-topic. We can do the reference counting a different way from cdtors if that's what works best. For further inquiry please start a discussion in the main forum. -- Andrei
_______________________________________________
Dlang-study mailing list
Dlang-study@puremagic.com
http://lists.puremagic.com/cgi-bin/mailman/listinfo/dlang-study

October 29, 2015
On 10/28/2015 08:29 PM, deadal nix wrote:
> I think it is very relevent here as destructor is a very common tool to
> free resources, as well as one of the most complex to deal with, mostly
> because of move semantic. I already had in mind to launch that subject
> before this whole thing started.
>
> Why were things changed that way ?

On second thought this might inform the best way to go about assigning responsibility for inc/decref across the caller and callee.

Regarding object copying: we noticed that in C++ it's difficult to define efficient move semantics and forwarding. This is because in a call line

fun(string("hello"));

even if fun "consumes" the string by either returning it or forwarding it to another function, the caller of fun must still destroy the rvalue created. In C++1x, if move semantics are at work, there's still a need for the callee to leave the moved-from string in a well-defined state so the destructor doesn't crash. All of that work is unneeded and is required for the sake of that destructor call.

In D a key element is that objects are relocatable, i.e. they can be moved across memory by using memcpy(). That makes it a more efficient protocol possible:

1. Caller calls the constructor
2. Object is bibblitted around
3. Object gets destroyed

So in D, perfect forwarding comes for "free" and we don't need a large feature such as C++'s rvalue references.

The disadvantage is you can't have value objects with internal pointers. (You can still have reference objects with internal pointers.)


Andrei
_______________________________________________
Dlang-study mailing list
Dlang-study@puremagic.com
http://lists.puremagic.com/cgi-bin/mailman/listinfo/dlang-study

October 29, 2015
Thanks, that's clearer.

2015-10-29 5:39 GMT-07:00 Andrei Alexandrescu <andrei@erdani.com>:

> On 10/28/2015 08:29 PM, deadal nix wrote:
>
>> I think it is very relevent here as destructor is a very common tool to free resources, as well as one of the most complex to deal with, mostly because of move semantic. I already had in mind to launch that subject before this whole thing started.
>>
>> Why were things changed that way ?
>>
>
> On second thought this might inform the best way to go about assigning responsibility for inc/decref across the caller and callee.
>
> Regarding object copying: we noticed that in C++ it's difficult to define efficient move semantics and forwarding. This is because in a call line
>
> fun(string("hello"));
>
> even if fun "consumes" the string by either returning it or forwarding it to another function, the caller of fun must still destroy the rvalue created. In C++1x, if move semantics are at work, there's still a need for the callee to leave the moved-from string in a well-defined state so the destructor doesn't crash. All of that work is unneeded and is required for the sake of that destructor call.
>
> In D a key element is that objects are relocatable, i.e. they can be moved across memory by using memcpy(). That makes it a more efficient protocol possible:
>
> 1. Caller calls the constructor
> 2. Object is bibblitted around
> 3. Object gets destroyed
>
> So in D, perfect forwarding comes for "free" and we don't need a large feature such as C++'s rvalue references.
>
> The disadvantage is you can't have value objects with internal pointers. (You can still have reference objects with internal pointers.)
>
>
>
> Andrei
> _______________________________________________
> Dlang-study mailing list
> Dlang-study@puremagic.com
> http://lists.puremagic.com/cgi-bin/mailman/listinfo/dlang-study
>