It makes sense that C++ avoids unnecessary copying or object creation whenever possible, that's pretty much C++'s M.O.
Old habits die hard? It used to always create a temporary right?
Temporaries could still be elided in some cases before, but the semantics were still understood in terms of temporary objects.
Now some forms of elision are mandatory and elision+RVO semantics are understood as objects being directly created into the final named location.
I find that understanding how memory is layed out in executable, how the C works in terms of stack, symbols etc is the introductory knowledge I had to obtain to even think about C++. Not sure what's there now, because I saw recently some great compiler warnings, but I'm pretty sure that I did convert a prvalue to a pointer reference (&) at least once in my life and later failed with memory problems, but no compiler errors
It will catch that and a lot of iffy stuff.
If you want to go deeper, you can also add your own diagnostics, which can have knowledge specific to your program.
https://clang.llvm.org/extra/clang-tidy/QueryBasedCustomChec...
C++ needs those extra categories, they exist for good reasons. But it is more complex.
const HUGE: usize = 10_000_000;
let mut values = Box::<[i32]>::new_uninit_slice(HUGE);
for k in 0..HUGE {
values[k].write(42);
}
let values = values.assume_init();
Edited to fix early enter oops, typo in loop length that'd be caught if I'd tried this.There’s some weird examples here involving functions, function pointers, template parameters, and a few other things.
Do you mean assignment?
Similarly just because a compiler may optimize a prvalue away doesn't change the fact that a prvalue by definition of the language is a temp.
It's like a tombstone for a deleted file, object - something that tells you - "Here lived Obj B Peterson, was nice folk, but moved away to a higher place"
Annoyingly, it depends on the type, sometimes with unintuitive consequences.
Move a unique_ptr? Guaranteed that the moved-from object is now null (fine). Move a std::optional? It remains engaged, but the wrapped object is moved-from (weird).
Move a vector? Unspecified.
I'm still baffled.
In these cases, something resembling "use after free" is unavoidable if the move is destructive even though the object is semantically dead. Putting the object in a sentinel state where it is alive but not usable captures the semantics of deferred destruction pretty well.
When you are decoupling memory lifetimes from object lifetimes it is pretty explicit. It isn't like this sneaks into your code on its own. You have to manage the implications of it yourself.
While there was only lvalue, and rvalue - it was easy - LEFT and RIGHT - gives you the right intuition.
But now - if it has identity - "glvalue" - why not "ivalue" or "idvalue"?
And then can be moved - "rvalue" ? Why "rvalue", why not "mvalue", or "move-value"? Why the language have to be so constricted when comes to such an important bit - I mean we spell "value" fully, but miss the important bit...
Anyway just a rant... I'm having the same issue understanding "math" sometimes because of all the cryptic notations, and archaic symbols used.
There have been a lot of times in science when I have trouble remembering names but have no trouble at all understanding the concepts behind these names. I just keep an index card nearby. I noticed this tendency of mine as early as high school. For example, in chemistry I sometimes couldn't remember which is dextro and which is levo, but I understand chirality and know how they are different. In physics I sometimes forget which is the magnetic B field and which is the magnetic H field, though I understand the difference between them. I don't use these concepts often so I haven't internalized the names. I think it's totally alright to have a name–concept dissociation for these.
Good luck explaining these "*values" to someone that hasn't touched C++ in a while. Then again other languages have the same peculiarities though. meh.
Here's a suggestion in retrospect:
| ivalue | pvalue
---------------------
lvalue | ilvalue | (plvalue)
rvalue | irvalue | prvalue
The current naming is confusing exactly because 'lvalue' should be a supertype in one dimension, just like 'rvalue', and not a subtype (here: 'ilvalue'). I think they took this shortcut because 'plvalue' doesn't really exist, but it's still inconsistent. Let's not even talk about 'xvalue' (here: 'irvalue').I also enjoyed the linked article about the 5 value types: https://blog.knatten.org/2018/03/09/lvalues-rvalues-glvalues.... For some reason I never bothered to look up these terms as they sounded so obscure. Turns out the taxonomy is pretty clear and it's just a refinement of the existing two value types (lvalues and rvalues).
EDIT: I do think the naming is rather confusing and inconsistent, though.
Given that it's an active discussion with all comments posted in the past few hours, I've created a new copy to give it its full opportunity for visibility and discussion.
dzdt•6d ago
There is a pretty good stack overflow post that quuxplusone linked below. How they explain it:
quuxplusone•5d ago
Now, if you don't know what "move semantics" is, then "lvalues can't be moved from" isn't terribly helpful, and if you do then it's tautological, so I'm not saying you're wrong to criticize. :) But in a C++ context, "move" does have a single specific meaning — the one he's using properly if opaquely-to-non-C++ers.
Conscat•7h ago
cjensen•7h ago
But here's the gist: sometimes you have an object you want to copy, but then abandon the original. Maybe it's to return an object from a function. Maybe it's to insert the object into a larger structure. In these cases, copying can be expensive and it would be nice if you could just "raid" the original object to steal bits of it and construct the "copy" out of the raided bits. C++11 enabled this with rvalue references, std::move, and rvalue reference constructors.
This added a lot of "what the hell is this" to C++ code and a lot of new mental-model stuff to track for programmers. I understand why it was all added, but I have deep misgivings about the added complexity.
[1] https://blog.knatten.org/2018/03/09/lvalues-rvalues-glvalues...
neonz80•6h ago