Move Constructors - Converting Lvalues to Rvalues
Timon Gehr
timon.gehr at gmx.ch
Thu Oct 3 00:57:44 UTC 2024
On 10/3/24 02:42, Timon Gehr wrote:
> Later if you add a move constructor, it will automatically select that
> as the appropriate choice.
About this, actually it might not do so with `-preview=rvaluerefparam`
sometimes because the rvalue-ness of the argument is not known statically.
Basically, let's assume S has both a copy constructor and a move constructor
```d
void byref(ref S s){ // ABI: passed by reference, caller cleanup
S t = s; // calls copy constructor
// ...
}
```
```d
void byval(S s){ // ABI: passed by value, callee cleanup
S t = s; // calls move constructor (with DIP1040)
// ...
}
```
```d
void bymove(@move S s){ // ABI: passed by reference, callee cleanup
S t = s; // calls move constructor (with DIP1040)
// ...
}
```
```d
byref(s); // passes &s, move constructor called 0 times overall
byval(move(s)); // moves s, has to call move constructor, move
constructor called twice overall
bymove(s); // semantically moves, actually passes &s. move constructor
is only called once, in the function body
```
Of course, you can do:
```d
void explicitmove(ref S s){
S t = move(s);
}
```
That would have similar semantics in practice as the `bymove` (though
the caller will always call the destructor with `explicitmove`, while
with `bymove`, the caller may be able to elide it). However, you had to
be explicit about it. It is not true that the code is upgraded for free,
because `byref` actually assumes that the caller is responsible for
cleaning up the parameter. This is true whether it is an rvalue or an
lvalue.
More information about the Digitalmars-d
mailing list