On Tuesday, November 5, 2019 5:09:15 AM MST Ferhat Kurtulmuş via 
Digitalmars-d-learn wrote:
> On Tuesday, 5 November 2019 at 12:06:44 UTC, Ferhat Kurtulmuş
>
> wrote:
> > On Tuesday, 5 November 2019 at 11:20:47 UTC, Mike Parker wrote:
> >> On Tuesday, 5 November 2019 at 10:32:03 UTC, Ferhat Kurtulmuş
> >>
> >> wrote:
> >>>>[...]
> >>
> >> I meant the example as an answer to your statement, "I wonder
> >> how new memory is allocated without an explicit malloc here".
> >> The postblit was intended as a chance to "fixup" everything
> >> when you needed a deep copy. The new struct is initialized as
> >> a shallow copy, so when you enter into the postblit, the
> >> pointer is already pointing at the original location. Without
> >> assigning it a new malloc'ed address, your memcpy was
> >> essentially overwriting the original location with its own
> >> data.
> >
> > What I need was a deep copy, and I thought I could have done it
> > using postblit constructor. Thanks for clarification.
>
> I think copy constructor is less confusing though.

It's pretty simple really. The compiler takes care of copying everything and
then the postblit constructor only has to worry about stuff where a deep
copy is needed. It's called a postblit, because it's run after the bit
blitting that's used to do a shallow copy. If an object has no postblit
constructor and has no member variables with postblit constructors, then all
a copy does is blit. When a D object with a postblit constructor is run, you
get three steps:

1. A shallow copy of the object is made by bit blitting it.
2. Then the postblit constructors (if any) of the member variables are run.
3. Then the postblit constructor for the object is run.

The result is that in your average postblit constructor, you only have to
deal with a portion of the member variables, whereas for a copy constructor,
you're forced to deal with _every_ member. In principle, postblit
constructors are actually a great idea, because they make it so that you
only have to worry about the members that actually need deep copies.

Where they fall apart is with modifiers like const. Because a postblit
constructor does a shallow copy and then you modify it, it requires
modification, which just doesn't work with const. So, while postblit
constructors were a good idea with D1 (which was a much simpler language),
with D2 (which added const as we know it), they've been far more of a
problem, which is why there was a DIP not long ago to add copy constructors
to D to replace postblit constructors. Because of how long postblit
constructors have been around, they may never actually be deprecated, but
ideally, newer code would use copy constructors, and over time, postblit
constructors wouldn't be used anymore.

Fortunately, D2 has fantastic metaprogramming, so it's actually possible to
write copy constructors that copy all of the members without having to
explicitly copy all of them by name. So, the main benefit of the postblit
constructor (not needing to explicitly copy everything) isn't as much of an
improvement as it originally was.

DIP: https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1018.md

It looks like the release that added copy constructors to the compiler was
2.086 back in May:

https://dlang.org/changelog/2.086.0.html
https://dlang.org/changelog/2.086.0.html#copy_constructor

So, while it's definitely useful for you to understand postblit
constructors, any code you're writing now should probably use copy
constructors. So, if you have a good understanding of copy constructors and
are having trouble with postblit constructors, presumably, that's an
improvement for you, though you may still need to deal with postblit
constructors in existing code that other people have written.

- Jonathan M Davis




Reply via email to