Discussion: Rvalue refs and a Move construtor for D
Exil
Exil at gmall.com
Wed Sep 4 21:09:27 UTC 2019
On Wednesday, 4 September 2019 at 09:20:05 UTC, kinke wrote:
> On Wednesday, 4 September 2019 at 00:33:06 UTC, Exil wrote:
>> How would it work with multi-function passing though? With a
>> rvalue reference, you are effectively just passing around a
>> reference, until the contents of the value are moved. So you
>> can pass it through N functions and it won't ever to do a
>> move/copy.
>>
>> Would you effectively be relying on the compiler to optimize
>> out the un-necessary moves, or would they be unavoidable, as
>> they effectively are now?
>
> Yes, by changing the ABI details to the C++ way in this regard,
> making move/forward intrinsics and detecting them in argument
> expressions. Laid out earlier in this thread in
> https://forum.dlang.org/post/jogsaeqxouxaeflmgzcc@forum.dlang.org. We don't need rvalue refs in the language for that at all, just use a value parameter - rvalue args will be passed by ref under the hood, just like explicitly moved lvalue args.
So you change the ABI to pass by a pointer to the object on the
stack. In cases where we use some "move" intrinsic, a pointer to
a lvalue (passed in to the move()) is passed in place of the
pointer to the object on the stack?
If I understand this correctly then this can happen:
struct Foo
{
int value;
}
void bar(Foo foo) // for rvalues, actually: `@rvalue ref Foo
foo`
{
// how do we know we are just changing the value of a
temporary
// that won't exist past this scope?
foo.value = 10;
}
void main()
{
Foo lvalue;
lvalue.value = 0;
bar(move(lvalue)); // intrinsic move
assert(lvalue.value == 10); // passes
}
Because of this, even though the function doesn't use a
reference. It could unknowingly change state outside of the scope
of the function. That'll entirely depend on the use if they
mistakenly use `move()` where they didn't mean to.
This would mean basically any current use of rvalue parameters
would need to be changed to be "const". And any function that
actually does need a copy would have to do so manually. They
don't know what is being passed to them, so it could very well be
making a copy twice.
void test(Foo foo)
{
Foo actualFoo = foo; // make copy just in case parameter
was `move`d in
actualFoo.value = 10;
}
Foo lvalue;
lvalue.value = 0;
test(lvalue); // makes 2 copies
assert(lvalue.value == 0); // ok
test(move(lvalue)); // makes 1 copy
assert(lvalue.value == 0); // ok
More information about the Digitalmars-d
mailing list