By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,227 Members | 1,376 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,227 IT Pros & Developers. It's quick & easy.

What is lvalue?

P: n/a
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.

--
Hongzheng Wang

Jul 22 '05 #1
Share this Question
Share on Google+
19 Replies


P: n/a
Hongzheng Wang wrote:
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)

Jul 22 '05 #2

P: n/a
"Gianni Mariani" <gi*******@mariani.ws> skrev i meddelandet
news:br********@dispatch.concentric.net...
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();

--
Dag Henriksson
Jul 22 '05 #3

P: n/a

"Hongzheng Wang" <wa******@mails.tsinghua.edu.cn> wrote in message
news:br**********@news.yaako.com...
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
Jul 22 '05 #4

P: n/a
Dag Henriksson wrote:
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.

Jul 22 '05 #5

P: n/a

"Rolf Magnus" <ra******@t-online.de> wrote in message
news:br*************@news.t-online.com...
Dag Henriksson wrote:
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.


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.

--
J.Schafer

Jul 22 '05 #6

P: n/a
Josephine Schafer wrote:

"Rolf Magnus" <ra******@t-online.de> wrote in message
news:br*************@news.t-online.com...
Dag Henriksson wrote:
> 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.


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.

Jul 22 '05 #7

P: n/a

"Rolf Magnus" <ra******@t-online.de> wrote in message
news:br*************@news.t-online.com...
Josephine Schafer wrote:

"Rolf Magnus" <ra******@t-online.de> wrote in message
news:br*************@news.t-online.com...
Dag Henriksson wrote:

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


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.


You are correct.
Syntactically the code is fine..I was just mixing two different things :-(.
Jul 22 '05 #8

P: n/a
On Tue, 09 Dec 2003 11:54:03 +0100, Rolf Magnus <ra******@t-online.de>
wrote:
Dag Henriksson wrote:
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.


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
Jul 22 '05 #9

P: n/a
> 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.

--
Dag Henriksson
Jul 22 '05 #10

P: n/a
"Rolf Magnus" <ra******@t-online.de> skrev i meddelandet
news:br*************@news.t-online.com...
Dag Henriksson wrote:
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.


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

--
Dag Henriksson
Jul 22 '05 #11

P: n/a
Dag Henriksson wrote:
"Gianni Mariani" <gi*******@mariani.ws> skrev i meddelandet
news:br********@dispatch.concentric.net...

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.


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.
Jul 22 '05 #12

P: n/a
"Gianni Mariani" <gi*******@mariani.ws> skrev i meddelandet
news:br********@dispatch.concentric.net...
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.

--
Dag Henriksson
Jul 22 '05 #13

P: n/a
Gianni Mariani wrote:
...
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 is essentially the same as the previous example. In this case 'C&
C::operator =(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.

--
Best regards,
Andrey Tarasevich

Jul 22 '05 #14

P: n/a

"Andrey Tarasevich" <an**************@hotmail.com> wrote in message news:vt************@news.supernews.com...
\
It seems like "C()" is an lvalue.


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.
Jul 22 '05 #15

P: n/a
Ron Natalie wrote:
"Andrey Tarasevich" <an**************@hotmail.com> wrote in message news:vt************@news.supernews.com...
\
It seems like "C()" is an lvalue.


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.


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++.

Jul 22 '05 #16

P: n/a
Gianni Mariani wrote:

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.

--
Best regards,
Andrey Tarasevich

Jul 22 '05 #17

P: n/a
Andrey Tarasevich wrote:
Gianni Mariani wrote:
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.

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 ?


Jul 22 '05 #18

P: n/a
Gianni Mariani wrote:
...
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 ?


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::operator =(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.

--
Best regards,
Andrey Tarasevich

Jul 22 '05 #19

P: n/a
Andrey Tarasevich wrote:
....

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::operator =(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.
Jul 22 '05 #20

This discussion thread is closed

Replies have been disabled for this discussion.