Live data from Hacker News

Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018)

blog.knatten.org

21–30 of 94 posts

Re: Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018)

#21
post #12

Earlier quoted context omitted.

> In general, if I need an rvalue and it's legal to convert the lvalue I have into an rvalue, the compiler should do it automatically. This is already done in some places. Example: std::unique_ptr get_int() { auto p = std::make_unique (1); // `p` is an lvalue but treated as an rvalue in the return statement. // (This would not compile otherwise because `p` is not copyable.) return p; }

That is the right approach IMO. What I'm basically saying is "more of this". It's clearly possible for C++ compilers to do this in many more cases. They already do most of the hard parts just to produce some of the error messages that they do. Why not use that knowledge more often to help the programmer instead of burdening them?

> It's clearly possible for C++ compilers to do this in many more cases. [...] Why not use that knowledge more often to help the programmer instead of burdening them?

Because it'd break code. I explained in another comment here: https://news.ycombinator.com/item?id=19634423

Re: Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018)

#22

Excellent explanation. Too bad it's necessary. && and std::move are the biggest warts in C++ (that's saying a lot), representing the need for programmers to be constantly aware of the less-than-obvious ways that a compiler might put an expression in one category or another. It's the programmer helping the compiler, instead of the other way around as it should be. In general, if I need an rvalue and it's legal to conv…

It's not what what you're asking is unreasonable in concept, but that it goes against how RAII is used in C++; it'd make more sense in a new language. Specifically the issue is that despite its name, RAII isn't merely used for resource acquisition, but also to define dynamic scopes. That means destroying an object too early (which can happen if an object is automatically moved) can cause a subsequent statement that d…

> it goes against how RAII is used in C++

That's an excellent point. To be honest, I think it's a problem with how RAII is used, conflating execution scope and object lifetime in a way that makes "move" a bit of a mess. That's why I prefer explicit "defer" like some languages have. Nonetheless, it's a common and useful enough idiom that breaking it is not something to be taken lightly. Maybe it's not really a solvable problem, given the paths that C++ took years ago, but I'd say "too bad it's necessary" is even more applicable if that's the case.

Re: Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018)

#23

lvalues are locatable, they represent an object that occupies some identifiable location in memory (has address). rvalues do not and therefore cannot be addressed (with & or *) I think of lvalues as things on the stack and rvalues as things stored in registers https://eli.thegreenplace.net/2011/12/15/understanding-lvalu...

> rvalues do not and therefore cannot be addressed (with & or *) Correction: prvalues cannot be addressed. There are also xvalues, which are both rvalues and lvalues i.e. they can be addressed but can also be moved from. In practice I think these are always lvalues that have been cast to an rvalue reference, usually using std::move().

This thread is recapitulating the article.

Re: Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018)

#24

Earlier quoted context omitted.

That is the right approach IMO. What I'm basically saying is "more of this". It's clearly possible for C++ compilers to do this in many more cases. They already do most of the hard parts just to produce some of the error messages that they do. Why not use that knowledge more often to help the programmer instead of burdening them?

> It's clearly possible for C++ compilers to do this in many more cases. [...] Why not use that knowledge more often to help the programmer instead of burdening them? Because it'd break code. I explained in another comment here: https://news.ycombinator.com/item?id=19634423

> Because it'd break code.

Then that's an indictment of the decisions that led to such code being written in the first place.

Re: Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018)

#25
post #19

Earlier quoted context omitted.

how can you have an lvalue stored in the heap? isn't the lvalue itself a pointer in the stack? obviously I see how it can have static storage.

If foo is an lvalue, then I believe (for example) *(foo[0].bar->baz) is also an lvalue, and those pointer dereferences can go anywhere. Those values occupy a location in memory, as you said, even if it isn't on the stack.

oh okay, understood. frankly I don't have an airtight understanding of the c++ standards and I would have considered your expression to be a dereference operation on an lvalue, but not an lvalue itself. ty for the explanation!

Re: Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018)

#26
post #20
post #17

Is this concept of lvalues, rvalues, glvalues, prvalues and xvalues only exists in C++?

Few other languages have move semantics. Rust does, but has a quite different value model overall.

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

Re: Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018)

#27

Earlier quoted context omitted.

> It's clearly possible for C++ compilers to do this in many more cases. [...] Why not use that knowledge more often to help the programmer instead of burdening them? Because it'd break code. I explained in another comment here: https://news.ycombinator.com/item?id=19634423

> Because it'd break code. Then that's an indictment of the decisions that led to such code being written in the first place.

Only if you're quick to judge without understanding why such code is and will continue to be written.

Re: Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018)

#28
post #19

Earlier quoted context omitted.

If foo is an lvalue, then I believe (for example) *(foo[0].bar->baz) is also an lvalue, and those pointer dereferences can go anywhere. Those values occupy a location in memory, as you said, even if it isn't on the stack.

oh okay, understood. frankly I don't have an airtight understanding of the c++ standards and I would have considered your expression to be a dereference operation on an lvalue, but not an lvalue itself. ty for the explanation!

I'm sure there are some complex exceptions, but as a starter, you can think of lvalues as "anything you can assign to" (the l basically stands for left, as in, "can appear on the left of an assignment"). So, if you have something like `foo(val) = 10`, then `foo(val)` is an lvalue.

Re: Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018)

#29
post #20
post #17

Is this concept of lvalues, rvalues, glvalues, prvalues and xvalues only exists in C++?

Few other languages have move semantics. Rust does, but has a quite different value model overall.

Our equivalent to lvalue/rvalue is “place expression” and “value expression” https://doc.rust-lang.org/reference/expressions.html#place-e...

Re: Lvalues, rvalues, glvalues, prvalues, xvalues, help (2018)

#30
post #26
post #20

Earlier quoted context omitted.

Few other languages have move semantics. Rust does, but has a quite different value model overall.

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

C++'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.
Post reply on HN