What is lvalue?

H

Hongzheng Wang

In K&R, they said:

An object is a named region of storage; an lvalue is an expression
refer to an object.

How about these concept in C++?
`The C++ Programming Language' has a similar explanation, however, it
may be too brief.

Can anyone give me a more detailed explanation? Or give some referrences
about it?

Thank you.
 
G

Gianni Mariani

Hongzheng said:
In K&R, they said:

An object is a named region of storage; an lvalue is an expression
refer to an object.

How about these concept in C++?
`The C++ Programming Language' has a similar explanation, however, it
may be too brief.

Can anyone give me a more detailed explanation? Or give some referrences
about it?

This was covered in the NG recently.

"lvalue" is short for "left hand side value" (of an assignment).

examples of non-lvalue expressions:

( 3 + 3 ) // you can't assign 3 + 3 !

( "str" ) // string can't be assigned either

These are "lvalues" :

int var;

var = 3 + 3; // var is an lvalue

* ( ( char * ) & var ) = "str"[2]; // * ((char *)&var) too

int & varref = var;

varref = 1["str"]; // varref is also an lvalue

int & func() { return var; }

func() = 2; // func returns a reference (lvalue)
 
D

Dag Henriksson

examples of non-lvalue expressions:

( 3 + 3 ) // you can't assign 3 + 3 !

( "str" ) // string can't be assigned either

in C++, string literals are l-values.

The explanation "l-values are something that can be at the right side of an
'='" is not a good explanation in C++. There are many examples of l-values
that cannot be assigned to and r-values that can be assigned to:

const int i = 5;
i = 2; // error. L-value 'i' not modifiable

struct C
{
C& operator=(int);
};

C() = 5; // OK to assign to r-value C();
 
R

Rolf Magnus

Dag said:
struct C
{
C& operator=(int);
};

C() = 5; // OK to assign to r-value C();

Would that really be ok? Assuming that your operator is supposed to
return a reference to the 'this' object, it would bind a non-const
reference to a temporary.
 
J

Josephine Schafer

Hongzheng Wang said:
In K&R, they said:

An object is a named region of storage; an lvalue is an expression
refer to an object.

How about these concept in C++?
`The C++ Programming Language' has a similar explanation, however, it
may be too brief.

Can anyone give me a more detailed explanation? Or give some referrences
about it?

Thank you.
Read this thread from comp.std.c++-
http://makeashorterlink.com/?H23F161C6

HTH,
J.Schafer
 
J

Josephine Schafer

Rolf Magnus said:
Would that really be ok? Assuming that your operator is supposed to
return a reference to the 'this' object, it would bind a non-const
reference to a temporary.

True.
But there are compilers (eg VC++) that do allow to bind non-const references to
temporary as an extension of the standard.
IMO, a conforming compiler should reject the code.
 
R

Rolf Magnus

Josephine said:
True.
But there are compilers (eg VC++) that do allow to bind non-const
references to temporary as an extension of the standard.
IMO, a conforming compiler should reject the code.

I'm not sure how the compiler could reject it. I was assuming that the
call to the operator is actually ok. The compiler cannot assume that
the operator will return a reference to the object it was called for
(could be a reference to another object in theory), so the validity
would be depending on the code of the operator, which the compiler
might not know.
 
J

Josephine Schafer

Rolf Magnus said:
I'm not sure how the compiler could reject it. I was assuming that the
call to the operator is actually ok. The compiler cannot assume that
the operator will return a reference to the object it was called for
(could be a reference to another object in theory), so the validity
would be depending on the code of the operator, which the compiler
might not know.

You are correct.
Syntactically the code is fine..I was just mixing two different things :-(.
 
T

tom_usenet

Would that really be ok? Assuming that your operator is supposed to
return a reference to the 'this' object, it would bind a non-const
reference to a temporary.

It's fine for member functions - you can call non-const member
functions on temporary objects. The well known vector::swap idiom
relies on this.

You can't directly bind a non-const reference to temporary, but you
can bind a non-const reference to non-const *this.

e.g.

struct C
{
C& ref()
{
return *this;
}
};

C& ref = C().ref(); //well-formed, but leaves dangling pointer.

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
 
D

Dag Henriksson

You can't directly bind a non-const reference to temporary,

That depends if the temporary is an lvalue or not. For example:

try {
throw 2;
} catch (int& i) {
}

Here, the temporary created in 'throw 2' must be an lvalue.
 
D

Dag Henriksson

Rolf Magnus said:
Would that really be ok? Assuming that your operator is supposed to
return a reference to the 'this' object, it would bind a non-const
reference to a temporary.

Yes,
C& operator=(int) { return *this; }
should be OK, since * operator yields an lvalue.
 
G

Gianni Mariani

Dag said:
"Gianni Mariani" <[email protected]> skrev i meddelandet




in C++, string literals are l-values.

yep - my bad. I was thinking...

&( "str"[0] )
The explanation "l-values are something that can be at the right side of an
'='" is not a good explanation in C++. There are many examples of l-values
that cannot be assigned to and r-values that can be assigned to:

const int i = 5;
i = 2; // error. L-value 'i' not modifiable

struct C
{
C& operator=(int);
};

C() = 5; // OK to assign to r-value C();

Here is the same without an operator=.

struct C
{
int a;

C()
: a(1)
{
}
};

int main()
{
C() = C();
}

It seems like "C()" is an lvalue.
 
D

Dag Henriksson

Gianni Mariani said:
struct C
{
int a;

C()
: a(1)
{
}
};

int main()
{
C() = C();
}

It seems like "C()" is an lvalue.

What makes you think that? C() is clearly an rvalue.
 
A

Andrey Tarasevich

Gianni said:
Here is the same without an operator=.

struct C
{
int a;

C()
: a(1)
{
}
};

int main()
{
C() = C();
}

It is essentially the same as the previous example. In this case 'C&
C::eek:perator =(const C&)' is used (it is implicitly declared by the
compiler).
It seems like "C()" is an lvalue.

I don't see what in this example makes you to conclude that 'C()' is an
lvalue.
 
R

Ron Natalie

Andrey Tarasevich said:
I don't see what in this example makes you to conclude that 'C()' is an
lvalue.
He makes the incorrect assumption that lvalue and rvalue have anything
to do with the assignment operator.

You can (as in this example) assign to an rvalue in some cases.
 
G

Gianni Mariani

Ron said:
He makes the incorrect assumption that lvalue and rvalue have anything
to do with the assignment operator.

You can (as in this example) assign to an rvalue in some cases.

This code produced as error :-

struct C
{
int a;

C()
: a(1)
{
}
};

template<typename T> void func()
{
T() = T();
}

int main()
{
func<C>();
func<int>();
}


error: non-lvalue in assignment

seems to be misleading ...


In "K&R C" land, the whole idea of the lvalue non-teminal was that it
could be on the LHS of an assignment or you could take the address of it
( operator &() ). Another "astonishment" event for C++.
 
A

Andrey Tarasevich

Gianni said:
This code produced as error :-

struct C
{
int a;

C()
: a(1)
{
}
};

template<typename T> void func()
{
T() = T();
}

int main()
{
func<C>();
func<int>();
}


error: non-lvalue in assignment

seems to be misleading ...

It is the 'func<int>' specialization that produces the error. 'int'
assignment uses built-in assignment operator, which indeed requires a
modifiable lvalue as its LHS.

I don't see anything misleading here. Built-in assignment _expects_
lvalue as its LHS. It doesn't _define_ lvalue as something that can be
used as LHS of built-in assignment.
In "K&R C" land, the whole idea of the lvalue non-teminal was that it
could be on the LHS of an assignment or you could take the address of it
( operator &() ). Another "astonishment" event for C++.

AFAIR, in K&R C the whole idea of "lvalue" was not much different form
ANSI C and C++ lvalue. The whole idea was that you could take the
address of it. Built-in assignment requires lvalue as its LHS.

Defining lvalue as "something that can be used as LHS of built-in
assignment" is nothing more than a distorted (reversed) form of the
above statement. Lvalue has never been defined this way.
 
G

Gianni Mariani

Andrey said:
It is the 'func<int>' specialization that produces the error. 'int'
assignment uses built-in assignment operator, which indeed requires a
modifiable lvalue as its LHS.

I don't see anything misleading here. Built-in assignment _expects_
lvalue as its LHS. It doesn't _define_ lvalue as something that can be
used as LHS of built-in assignment.




AFAIR, in K&R C the whole idea of "lvalue" was not much different form
ANSI C and C++ lvalue. The whole idea was that you could take the
address of it. Built-in assignment requires lvalue as its LHS.

Defining lvalue as "something that can be used as LHS of built-in
assignment" is nothing more than a distorted (reversed) form of the
above statement. Lvalue has never been defined this way.


I'm not sure what argument you are making ... so is C() and lvalue ?

Did I just misread the earlier posts saying that C() is an rvalue ?

Is ( C() = C() ) not using the "built-in" assignment ?
 
A

Andrey Tarasevich

Gianni said:
I'm not sure what argument you are making ... so is C() and lvalue ?

No, it is an rvalue.
Did I just misread the earlier posts saying that C() is an rvalue ?

No, you didn't. 'C()' is indeed an rvalue.
Is ( C() = C() ) not using the "built-in" assignment ?

No, it isn't. 'C() = C()' in the previous example is using the
implicitly declared operator 'C& C::eek:perator =(const C&)'. This operator
does not require lvalue as its LHS. Note that implicitly declared copy
assignment operators are not referred to as "built-in operators" in C++
terminology.
 
G

Gianni Mariani

Andrey Tarasevich wrote:
....
No, it is an rvalue.




No, you didn't. 'C()' is indeed an rvalue.




No, it isn't. 'C() = C()' in the previous example is using the
implicitly declared operator 'C& C::eek:perator =(const C&)'. This operator
does not require lvalue as its LHS. Note that implicitly declared copy
assignment operators are not referred to as "built-in operators" in C++
terminology.

OK - thanks.

My earlier point was that this error statement is misleading because it
is incomplete.

"error: non-lvalue in assignment"

This error should read somthing like (don't laugh..ok):

"error: non-lvalue in built-in assignment" (suggestions welcome)

Or somthing to that effect. I was quite aware that the int()=int() was
the problem, I was simply highlighting that the same code (template)
could work for one type and fail for another and the error message was
somewhat inadequate. In fact, I'm going to file a gcc bug - I'm sure
this message genealogy is from the C compiler and is a little misleading.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top