Comment by ghm2180

10 hours ago

> Let me put this in simpler terms: std::move is like putting a sign on your object “I’m done with this, you can take its stuff.”

and later:

> Specifically, that ‘sign’ (the rvalue reference type) tells the compiler to select the Move Constructor instead of the Copy Constructor.

This is the best conceptual definition of what `std::move` is. I feel that is how every book should explain these concepts in C++ because its not a trivial language to get into for programmers who have worked with differently opiniated languages like python and java.

If you read Effective Modern C++ right Item 23 on this, it takes quite a bit to figure out what its really for.

In simpler terms

1. You must implement a move constructor or a move assignment operator in order for std::move to do anything

2. The moved object could be left in an unusable state, depending on your implementation, after stealing its internal resources.

  • I never understood move semantics until I learned Rust. Everything is move by default and the compiler makes sure you never leave things in an unusable state.

    This was a difficult mental hurdle to get over with Rust, but once you do, move semantics make a lot more sense.

    edit: When I said everything is move by default, I mean everything that isn't "Copy", such as integers, floats, etc.

    • What Rust loses with that decision is the ability to program the "semantics" in move semantics. Rust has no distinction between hypothetical place constructor and value constructor.

      2 replies →

  • > You must implement a move constructor or a move assignment operator in order for std::move to do anything

    Bit of a nitpick, but there are sometimes other functions with overloads for rvalue references to move the contents out - think something like std::optional's `value() &&`. And you don't necessarily need to implement those move constructor/assignment functions yourself, typically the compiler generated functions are what you want (i.e. the rule of 5 or 0)

  • > The moved object could be left in an unusable state, depending on your implementation, after stealing its internal resources.

    The "proper" semantics are that it leaves the object in a valid but unspecified state. So, invariants still hold, you can call functions on it, or assign to it.

I thought "move doesn't move" was a fairly common C++ mantra at this point.

  • > I thought "move doesn't move" was a fairly common C++ mantra at this point.

    It is. The fact that std::move is just a cast and that move constructors are expected to transfer resources are basic intro to C++ topics, covered in intro to constructors.

    • It's far too late to put the genie back in the bottle, but I am morbidly curious as to why the standards committee didn't choose an approach that made moves destructive.

      5 replies →

I read Effective Modern C++ years ago and was confused exactly like what you describe.

Modern C++ is hard to get into for people who learned C++ in the 90s and then worked in other languages for a decade or two.