4 ms·
It’s not just for disposing things, it’s also used to decompose things into their constituent parts… like if I had something representing an HTTP response and i
by ninkendo 1y ago
It’s not just for disposing things, it’s also used to decompose things into their constituent parts… like if I had something representing an HTTP response and it contains headers and a body, I could write a `fn into_parts(self) -> (Headers, Body)` that returns the parts you care about while destroying the response object.
This is useful in the grpc library I use, which has a response type with some metadata about the response, and an “inner” value that represents the thing the grpc method returned. If you just want the inner thing and don’t care about the metadata, there’s a `fn into_inner(self)` that destroys the response and leaves you the inner value.
You can write similar methods in C++ but they require leaving the original value in an “empty” state so that you can avoid expensive copying of things while still letting the moved-from value be “safe” to use. But that affects your API design… you now have to make the methods that fetch the “inner” thing be nullable/optional so that you can represent “oh this was moved from so there’s no body any more”. You don’t have to do that in Rust: moves are just a memcpy and the compiler will reject programs that use the moved-from value.
- fooker 1y ago> compiler will reject programs that use the moved-from value. Yes, this is something the C++ 'language' is not going to specify other than claiming that it is undefined behavior. Doesn't prevent compilers from doing it though, clang will happily do this for you right now in most cases. https://discourse.llvm.org/t/rfc-intra-procedural-lifetime-analysis-in-clang/86291 https://discourse.llvm.org/t/rfc-intra-procedural-lifetime-a...
- ninkendo 1y agoBut it's not undefined behavior. That's the key. It's "unspecified behavior", meaning that according to the standard, it's allowed. A program that reuses a moved-from value is considered valid and well-formed by the standard. It merely delegates how to make this work to the individual implementation (a string becomes an empty string, a vector becomes an empty vector, etc.) The RFC you posted has nothing to do with move semantics, it's about references outliving what they point to (ie. use-after-free, etc) and similar to Rust's borrow checker. But here's the thing: move semantics and the borrow checker have nothing to do with each other! The borrow checker ensures that borrowed data (ie. &Foo, equivalent to C++'s references) is sound, it's not the part that enforces move semantics. That happens earlier in the compilation, the compiler enforces moves well before the borrow checker phase.