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