D's equivalent to C++'s std::move?

Atila Neves via Digitalmars-d digitalmars-d at puremagic.com
Thu Feb 11 06:25:39 PST 2016


On Wednesday, 10 February 2016 at 22:32:54 UTC, Ola Fosheim 
Grøstad wrote:
> On Wednesday, 10 February 2016 at 20:42:29 UTC, w0rp wrote:
>> Back on the original topic, Scott Meyers often says "std::move 
>> doesn't move." It's more like std::rvalue_cast. C++ uses 
>> r-value references in order to be able to rip the guts out of 
>> objects and put them into other objects.
>
> Well. In C++ "std::move(x)" is just a "static_cast<T&&>(x)" for 
> "T x".
>
> "T&&" references are different from "T&" by acting like T& 
> references when used, but not on overloads. They are primarily 
> for distinguishing between overloads on temporaries in function 
> calls, T&& binds to temporaries. So you use "std::move(x)" to 
> tell the type system that you want it to be cast as a 
> references to a temporary like reference (or rvalue reference).
>
> So that's why constructors with "T&&" are called move 
> constructors (taking stuff from temporaries) and "const T&" are 
> called copy constructors (assuming that the parameter might 
> have a long life on it's own).
>
>> That kind of return value optimisation was the original 
>> motivation for r-value references, for when C++98 RVO isn't 
>> good enough, from my understanding.
>
> It is for overloading. Why allocate lots of stuff by copying it 
> if you know that the referenced object is about to die anyway? 
> If it is dying we just steal the stuff it is holding.
>
> stack.push(string("hiii")) // we could steal this stuff
> string x("hiii")
> stack.push(x) // we have to copy this stuff
>
>> Maybe someone else will correct me on a point or two there, 
>> but that's the understanding of move semantics in D that I 
>> have had.
>
> I don't think D has move semantics... It does copying and 
> clearing... The postblit thing looks like a dirty hack to me.

D has move semantics. Deep copies are done with post-blit. Fair 
enough if you just:

auto foo = bar;

Then it's a shallow copy. The only difference to a "true" move is 
that bar isn't T.init, but that's easily done with the move 
function (assuming the struct has a destructor) or manually.


C++:

void foo(Foo); //copy
void foo(Foo&); //by-ref, only lvalues
void foo(Foo&&); //move, only rvalues

D:

void foo(Foo); //copies copiable types, moves non-copiable ones
void foo(ref Foo); //by-ref, only lvalues


In D, the foo(Foo) variant can be called with lvalues as long as 
they don't @disable this(this). Any type that does isn't copiable 
so you can only pass rvalues in.

Atila


More information about the Digitalmars-d mailing list