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