Move Constructor Syntax

Timon Gehr timon.gehr at gmx.ch
Sun Oct 13 01:37:47 UTC 2024


On 10/13/24 01:33, Manu wrote:
> On Sun, 13 Oct 2024, 07:17 Timon Gehr via Digitalmars-d, <digitalmars- 
> d at puremagic.com <mailto:digitalmars-d at puremagic.com>> wrote:
> 
>     On 10/11/24 09:25, Manu wrote:
>      > I don't see how elevating this declaration to a move-constructor
>      > actually changes the semantics at all... I don't think it does? I
>     think
>      > this function ALREADY IS A MOVE CONSTRUCTOR (at least; it's an
>     rvalue-
>      > constructor, which is the same thing from a semantic
>     perspective); it's
>      > just working with an inefficient calling convention.
>      > Move semantics as proposed simply improve this code, no?
> 
>     DIP1040 suggests to pass the argument implicitly by reference and to
>     not
>     call the destructor on it.
> 
>     As I mentioned in my DConf talk, this can lead to accidental memory
>     leaks. Particularly if it is existing code that previously assumed the
>     destructor will run.
> 
> 
> I feel like we resolved this; we agreed that the no destructor call in 
> 1040 was a mistake.

Yes, I think that's the best resolution, but you asked "how can 
elevating a declaration to a move constructor change semantics", and not 
everyone may be on the same page what a move constructor is, especially 
as DIP1040 specifies something else. In particular, this may be part of 
what the person you were replying to (Jonathan? you didn't specify the 
author) had in mind.

> If the callee decides to do anything invasive with 
> its argument, like stealing it's allocations in a move operation, it 
> must return it to a destructible state. The memory's lifetime in the 
> calling code would continue, and call the destructor as usual.
> 
> I felt confident we agreed on that requirement and it resolved the 
> issues you illustrated?
> ...

Yes, this is one way to handle that. Personally I do not like the whole 
"destructible state"/.init thing a lot, but I think it does work about 
as well as null pointers in the worst case.

Also, having the caller be responsible for destruction of rvalue 
arguments is a bit unfortunate as it prevents tail calls, but it is 
unlikely to work out anyway given Walter wants to preserve DIP1000 
semantics for lifetimes.

>     Another point where it will differ is automatic generation of move
>     constructors and move `opAssign`. I think now it has to be done
>     manually
>     or you get copies.
> 
>     Finally, for some reason, at the moment you cannot have both `this(ref
>     S)` and `this(S)`. But `opAssign(ref S)` and `opAssign(S)` works. This
>     moves around values in memory a bit more often though. A semantic move
>     may just pass a reference further down the call stack.
> 
> 
> Yes, pretty much the entire point of this work is enabled passing the 
> point "further down the line", copying at each function boundary is 
> precisely the problem to be solved.
> 
>     (IIRC non-POD
>     struct types are always passed by `ref` in the ABI.)
> 
> 
> Yes, essentially, we're just acknowledging in the language semantics 
> what is already true in the ABI.
> 

Yup.


More information about the Digitalmars-d mailing list