Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rvalue on the left side

Why is this code compiling? I thought that rvalues returned by ctor are not located in memory and therefore can't be used as lvalues.

#include <iostream>
#include <vector>

class Y {
public :
    explicit Y(size_t num = 0)
    : m_resource {std::vector<int>(num)}
    {
    }

    std::vector<int> m_resource;
};

int main(int argc, const char * argv[]) {
    Y(1) = Y(0); // WHAT?!?
    return 0;
}
like image 858
John Difool Avatar asked Jan 17 '16 06:01

John Difool


People also ask

What is L and R value?

An lvalue (locator value) represents an object that occupies some identifiable location in memory (i.e. has an address). rvalues are defined by exclusion. Every expression is either an lvalue or an rvalue, so, an rvalue is an expression that does not represent an object occupying some identifiable location in memory.

What are the left and right values lvalue & rvalue )?

lvalues are “left values”: expressions that can be assigned to, which can be on the left of an assignment. rvalues are “right values”: everything else, which must be on the right of an assignment.

Where is rvalue stored?

But where exactly is this rvalue stored? It's up to the compiler where to store a temporary; the standard only specifies its lifetime. Typically, it will be treated like an automatic variable, stored in registers or in the function's stack frame.

Are R values and hence the may not assigned and Cannot appear on the left hand side?

Variables are lvalues and hence they may appear on the left-hand side of an assignment. Numeric literals are rvalues and hence they may not be assigned and cannot appear on the left-hand side.


2 Answers

The synthesized assignment operator is declared as one of these (if it can be synthesized and isn't declared as deleted) according to see 12.8 [class.copy] paragraph 18:

  • Y& Y::operator=(Y const&)
  • Y& Y::operator=(Y&) ()

That is, like for any other member function which isn't specifically declared with ref-qualifiers it is applicable to rvalues.

If you want to prevent a temporary object on the left hand side of the assignment you'd need to declare it correspondingly:

class Y {
public :
    explicit Y(std::size_t num = 0);
    Y& operator= (Y const&) & = default;
};

The standard uses the name ref-qualifier for the & before the = default. The relevant proposal is N2439. I don't know where there is a good description of ref-qualifiers. There is some information at this question.

like image 72
Dietmar Kühl Avatar answered Oct 13 '22 03:10

Dietmar Kühl


Not sure where you got that specific rule of thumb. If any, a rule of thumb would be (from Scott Meyers): if it has a name, it's an lvalue.

In this case, you're creating a temporary object and passing it to an assignment method/function. There is no problem with that. In fact, it might even make sense to do so, as in

// Applies foo to a copy, not the original.
(Y(1) = y).foo()

It is true that Y(*) don't have names here, though, and hence they are rvalues.

like image 20
Ami Tavory Avatar answered Oct 13 '22 03:10

Ami Tavory