| ▲ | ghm2180 6 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. |
|
| ▲ | qbane an hour ago | parent | next [-] |
| I read Effective Modern C++ years ago and was confused exactly like what you describe. |
|
| ▲ | yunnpp 4 hours ago | parent | prev | next [-] |
| I thought "move doesn't move" was a fairly common C++ mantra at this point. |
| |
| ▲ | locknitpicker 4 hours ago | parent [-] | | > 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. | | |
| ▲ | LexiMax 2 hours ago | parent [-] | | 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. | | |
| ▲ | jandrewrogers an hour ago | parent [-] | | It solves some rare edge cases where the destruction of the moved-from object must be deferred -- the memory is still live even if the object is semantically dead. Non-destructive moves separate those concerns. There is a related concept of "relocatable" objects in C++ where the move is semantically destructive but the destructor is never called for the moved-from object. C++ tries to accommodate a lot of rare cases that you really only see in low-level systems code. There are many features in C++ that seem fairly useless to most people (e.g. std::launder) but are indispensable when you come across the specific problem they were intended to solve. |
|
|
|
|
| ▲ | dsnr 5 hours ago | parent | prev | next [-] |
| 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 5 hours ago | parent | next [-] | | 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 4 hours ago | parent [-] | | 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 3 hours ago | parent [-] | | 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 |
|
| |
| ▲ | grogers 4 hours ago | parent | prev | next [-] | | > 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 3 hours ago | parent | prev [-] | | > 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 2 hours ago | parent [-] | | > you can call functions on it Only functions with no preconditions, unless the type makes more guarantees as to the moved-from state. | | |
| ▲ | jjmarr 24 minutes ago | parent [-] | | 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. |
|
|
|
|
| ▲ | QuercusMax 5 hours ago | parent | prev [-] |
| 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. |