5 ms·
Is this concept of lvalues, rvalues, glvalues, prvalues and xvalues only exists in C++?
by bagol 7y ago
Is this concept of lvalues, rvalues, glvalues, prvalues and xvalues only exists in C++?
- Sharlin 7y agoFew other languages have move semantics. Rust does, but has a quite different value model overall.
- cesarb 7y agoAlso, Rust does not have copy or move constructors/operators; every copy or move is a pure memcpy() (there's Clone for when you need it, but clone is always an explicit call). This simplifies the model a lot.
- htfy96 7y agoC++'s move constructor can throw exceptions. An example would be moving a linked list, and the allocation of dummy tail node can fail. In my opinion, the design choice to support recoverable allocation failure in C++ reasons for most other designs.
- steveklabnik 7y agoYou can make allocation failure recoverable in different ways. For example, Rust’s (yet to be stabilized) allocator API returns a Result: https://doc.rust-lang.org/stable/std/alloc/trait.Alloc.html#tymethod.alloc https://doc.rust-lang.org/stable/std/alloc/trait.Alloc.html#... It is true that choosing to make this recoverable is a big part of it; in Rust we decided to make standard library data structures treat allocation as unrecoverable, and this does simplify the API of using them significantly. However, I would argue that the complexity in C++ comes more from using exceptions for this purpose than from that choice. Rust’s panics being used for unrecoverable errors only helps simplify the overall model. In other words, the ease of use goes unrecoverable > recoverable through result > recoverable through exceptions, and the model complexity comes from the choice of using exceptions over return values. We do have a plan for introducing a way to make the data structures recoverable, but it’s waiting on several things. This is, of course, only my opinion.
- htfy96 7y agoException is also a result of supporting recoverable allocation/construction failures, IMO. When you need to support a failable Vec::new, what will be the type of its Error? There are two choices in this case: a) wrap underlying errors into something like VecNewError, which is tedious due to the prevalence of errors if every construction/allocation can fail, kindly similar to the CheckedException dilemma b) type erasing it by Box it or dyn Error, and use ? operator to transparently pass errors to upper level, in which case the user need to downcast with match to extract information needed, and exception is essentially the syntax sugar for this case because exception acts like a ? operator after all failable function calls a) is usually used in a language where errors are rare, and b) is preferred when the errors are common.
- Rusky 7y agoVec::new doesn't allocate. Vec::try_reserve, on the other hand, simply uses a common `CollectionAllocError`, which is not really (a) or (b).
- dbaupp 7y agoWhy would moving a list have to allocate a new tail node? A lot of the value in moves is passing data around without having to copy/duplicate/allocate. The most useful aspect of having customisable move constructors like in C++ seems to be things like updating pointers in self-referential types, which hopefully can be written to never throw.
- Rusky 7y agoRust moves don't allocate, and yet can still support recoverable allocation failure. The reason C++'s model is so much more complicated is because of backwards compatibility and nondestructive moves, not as a mechanism to support recoverable allocation failure.
- steveklabnik 7y agoOur equivalent to lvalue/rvalue is “place expression” and “value expression” https://doc.rust-lang.org/reference/expressions.html#place-expressions-and-value-expressions https://doc.rust-lang.org/reference/expressions.html#place-e...
- nixpulvis 7y agoI like that so much more!
- mjn 7y agolvalue/rvalue are old concepts and terms ('60s/'70s) and common to all C-family languages. The others are new to C++.