Comment by dsnr

Comment by dsnr 11 hours ago

8 replies

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.

bitbasher 10 hours ago

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.

  • Conscat 10 hours ago

    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.

    • anematode 9 hours ago

      A loss of functionality, but arguably a good thing, e.g. moving will never throw an exception/panic so you don't need an equivalent to is_nothrow_move_constructible

    • lowq 4 hours ago

      I sure don't miss the footguns and raw boilerplate that is having a copy constructor, move constructor, copy assignment operator, move assignment operator, and destructor, per class.

      Yes, you should avoid the manual memory management that necessitates writing them. But work with a team of developers fresh out of school and next thing you know your codebase will be brimming with this kind of busywork.

grogers 10 hours ago

> 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)

jjmarr 9 hours ago

> 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.

  • masklinn 8 hours ago

    > you can call functions on it

    Only functions with no preconditions, unless the type makes more guarantees as to the moved-from state.

    • jjmarr 6 hours ago

      The guarantees is that a moved-from state is in an otherwise valid state.

      So, you can do things like check if a moved from std::vector is empty (often the case in practice), then start appending elements to it.