Left and right values in C + +

Source: Internet
Author: User
Tags call by reference

+ + (a++)
a++ equivalent to
int A;
{
int temp=a;
a++;
Teturn temp;
}
So we can treat + + (a++) as ++temp, and temp
Obviously is a right value, so can not use AH ~ ~

The L in L-value refers to location, which indicates addressable. The "L" in Lvalue can is though of as location
R in R-value refers to read, which indicates readable. The "R" in Rvalue can is thought of as "read" value.

Lvalue Right Value

Lvalue (Lvalue) and Rvalue (rvalue) are two very basic concepts in programming, but it is also very easy to misunderstand, read a lot of articles, self-feeling really will this problem speak very thorough article has not seen, so volunteered to try. If the concept of Lvalue rvalue is not very clear, then sooner or later they will jump out like a stumbling block, annoying you, like playing computer games when there are always a few mines to test your patience, if you sweep all the mines to the best. :)

The Lvalue (lvalue) and Rvalue (rvalue) are derived first from the compilation theory (thanks to the programs of the South-sized lilies). In the C language, two values are represented on either side of the assignment operator, and the left is called the left value, and the right is called the rvalue. Like what:

int II = 5;//II is an lvalue, 5 is the right value

int JJ = II;//JJ is an lvalue and II is the right value

The above shows that the lvalue can certainly be used as the right value, but not otherwise. The earliest difference between the left and right values is the ability to change. The left value can be changed, and the right value cannot be changed. "Note 1"

Note 1: This in C + + has been a pig sheep discoloration, no longer established. Arch Pig game is still very fun, I really grabbed a few times all hearts, but really good risk. :)

In many articles, it is mentioned that in C + +, the left value more refers to the can be positioned, that is, the value of the address, and the right value does not have an address. "Note 2"

Note 2: This is still inaccurate, I generate a temporary rvalue std::vector () in the program, can you say it has no address? Is it a ghost or a ghost without a body? It has an address, and it is also an absolute right value.

In modern C + +, the left and right values are now basically lost in their original meaning, and for lvalue expressions, an object is specified by a specific name and reference (pointer or reference). A non-lvalue is a right-hand value. I'll take the next definition:

An lvalue indicates that the program must have a specific name referenced to this value.

An rvalue indicates that no particular name in the program refers to this value.

It has nothing to do with whether they can be changed in stacks or heaps (stack or heap).

1 . Left value

In the following code:

int II = 5;

int const JJ = II;

int a[5];

A[0] = 100;

* (a+3) = 200;

int const& max (int const& A, int const& b)//call by reference

{

Return a > B? A:B;

}

int& Fun (int& a)//call by reference

{

A + = 5;

return A;

}

ii,jj,a[0],* (a+3), and the return value of the function max, such as Max (II, JJ), the return value of the "Note 3" function fun (ii) are left values. , they are all values that have a specific reference name. ii,jj,a[0],* (a+3), Max (II, JJ), Fun (ii) are their names, respectively.

Note 3: Here is a blind spot that is less easily divided. That is, someone will ask Max (8, 9) Whether the arrival is an lvalue or an rvalue, the C + + standard specifies that the constant reference (reference to const) can refer to the rvalue, so Max (8, 9) seems to be the right value, but whether it is an lvalue or an rvalue, we can't try to change it. In order to be consistent with the previous concept, I think it is an lvalue, an immutable constant left-hand value.

The lvalue is immutable, that is, the left value modified by the const, such as the Jj,max (ii, JJ) above, is trapped by the constant (const) enchantments.

The value of the Lvalue, which is not trapped by const, is, of course, possible to change, for example, the following code is true:

II = 600;

A[0] = 700;

Fun (ii) = 800; Ok!

There is no problem with our eyes, fun (ii) = 800; absolutely correct, because it is the left value that can be changed. So if we look at the STL source code, we will understand why the return value of the overloaded operator[] operator in Std::vector is written as a reference, because operator[] must return an lvalue.

2 . Right value

A value that does not have a specific name is the right value. Let's look at the following code:

Std::list ();

Std::string ("It is a rvalue!");

int fun1 ()//call by value

{

...

}

int* fun2 ()//call by reference

{

...

}

where Std::list (), std::string ("It is a rvalue!"), the return value of the function Fun1 fun1 (), the function fun2 the return value fun2 () are the right values, and their values do not have a specific name to refer to. Perhaps some people will wonder, fun2 () is also the right value? is the top Max (A, A, a, b) not an lvalue?

See clearly that the return value of the function fun2 is Pointer,pointer is also call by value, and the return value of the function Max is reference,reference is call by reference. So the introduction of reference in C + + is not just for convenience, it is also a must. "Note 4"

Note 4:scott Meyer wrote the "more effective C + +" clause 1 specifically told the difference between pointer and reference, written very well, distinguished very clearly.

Fun2 () is an rvalue, but *fun2 () is an lvalue, just like the *p that is often seen, so when you look at C + + library code, you will find that the return value of the overloaded operator* function is reference.

Of course, I also missed a right value, that is, the literal (literal) value, such as 5,8.23, ' a ' and so on is certainly the right value.

When the right value first appears, one of the biggest features is that it cannot be changed. But as with our moral standards, the times are different, the standards have changed, and the former five virtues have been thrown into the rubbish heap of history.

C + + has the right value that can be changed, and this feature is also very useful. That is the temporary object that is generated by the constructor of the user-defined classes (class). Like what:

Std::vector (9), std::d eque (), ... Are the right values that can be changed. In Herb Sutter's "more exceptional C + +" Article 7 of the Page51 page has such a few lines of code:

Example 7-2 (b): The right-shrink-to-fit a vector.

Vector<customer> C (10000);

... now c.capacity () >= 10000 ...

Erase all but the first ten elements

C.erase (C.begin () +10, C.end ());

The following line does shrink C ' s

Internal buffer to fit (or close)

Vector<customer> (c). Swap (c);

... now c.capacity () = = C.size (), or

Perhaps a little more than c.size ()

Watch it a few times, and you'll find that the size of the vector increases to a certain extent, you don't need so much space, you will find a way to shrink it to the most appropriate size, but use other methods such as the Call member function reserve () can not do, this time must use the right value to change the nature.

Vector<customer> (c). Swap (c); This line of code is the point of the finishing touches.

First use the copy constructor to generate a temporary rvalue vector<customer> (c), the right value is exactly the right size, and then the C Exchange "Note 5", C becomes the appropriate size, and finally at the end of the entire expression, the temporary right-to-left destructor to return the memory space. It's a gentleman's elegance!

Note 5: This time the temporary right value has changed.

If you don't understand it, you can read the book or look directly at the source code of the library.

And why is that? I thought about it, I think so, we look at the class data layout structure, we will find that every member of its data has a name, I think the compiler in the process of compiling, will generate an externally unknown to the temporary object of the right value of the name reference, but need to change this temporary object, This name is used. Like what:

Class Point

{

Public://For convenience only, I expose data members, in reality try not to use this

int x, y, Z;

...//other various member functions

};

We can now change the right value, using the anonymous reference name.

Point (). x = 6;//Changed the right value

Point (). y = 6;//agrees to change the right value, but note that the right value is not the same as the one above.

Summarize

The real difference between lvalue and rvalue I guess that's it. The lvalue indicates a specific name reference, and the right value does not have a specific name reference. Of course, I will still have negligence, I hope you can remind me to correct my shortcomings.

The first two days to see Herb Sutter Mail from the new article (I subscribe to his new article email notification), one is about the tuple data structure, there is nothing new, it seems to have seen before, there is a name is: (Mostly) Private, the address is/HTTP www.cuj.com/documents/s=8273/cujcexp2107sutter/content itself is not deep, but after reading the article, found ubiquitous C + + paradox Cloud deepness, but also what is called the sleeve in the universe, water more than a perceptual knowledge.

In the next article I would like to discuss from my own experience, from a different perspective, how the graduates in the IT industry find jobs, and I want to make all readers think about it, not just job seekers. I have already thought of the topic, called "Play Tiger to eat pig", but now I have some other things to be busy, so may let everybody wait a few days.

Reprint please indicate the source, thank you!

Wutongguang written in 2003.6.20

Last modified 2003.6.21

Lvalue (Lvalue), Rvalue (rvalue) is an obscure concept that some people may not even hear, but this concept becomes very important after c++11, which is the basis for understanding new semantics such as Move (), forward ().

What is an lvalue right-hand value?

The two concepts of lvalue and rvalue are inherited from C, in C, the lvalue refers to the variable (expression) that can appear to the left and right of the equals sign, and the right value refers to the variable (expression) that can only appear to the right of the equal sign.

int A;  int34; a = b;b = A;  not legal. 3 =4;          

Usually, a variable with a name is an lvalue (as in the example above, A, b), and the intermediate result (no name) produced by the operation (subtraction, function call return value, etc.) is the right value, such as 3+4 on, A + B, and so on.

For the moment, we can assume that the lvalue is something that can be found in a program, and the right value is something that cannot be taken to its address (not exactly).

As the concept is in C + +, it becomes slightly different.

In C + +, each expression produces an lvalue, or rvalue, and, accordingly, the expression is called an lvalue expression and an rvalue expression. For built-in data types (build-in types), the concept of lvalue rvalue is not much different from that of C, except that the custom type is different.

And this difference is easy to confuse:

1) for the built-in type, the right value is not modifiable (non-modifiable) and cannot be modified by const, volatile (Cv-qualitification ignored)

2) for a custom type (user-defined types), the right value is allowed to be modified by its member function.

for 1), which is consistent with C, 2) is unique in C + +, so if you see the following notation in C + +, there might be some surprises:

Classcs{Public: CS (int i): I_ (i) {cout <<"Cs"<< I <<") constructor!"<<Endl } ~cs () {cout <<"CS Destructor,i ("<< I_ <<")"<<Endl } cs&Operator= (Const cs&Other) {I_ =Other.i_; cout <<"CS operator= ()"<<Endlreturn *This; }int get_i ()const {ReturnI_; }void Change (int i) {i_ =I }Private:int i_;}; CS Get_cs () {static int i = 0return cs (I++int main () {// legal (Get_cs () = CS (2)). Change (323); Get_cs () = CS (232); return 0    

This feature is somewhat odd, and in general, the custom type in C + + should be designed to be as true as the built-in type, but this feature violates this principle.

For this feature, we can actually think of the point: The custom type allows the member function, and the call member function through the rvalue is allowed, but the member function may not be a const type, so by calling the right-valued member function, it is possible to modify the right value, done!

lvalue Reference, rvalue reference

Another area to note about Rvalue is that the rvalue can be pointed to by a reference to the const type

ref = Get_cs ();

And can only be pointed to by the const type of reference:

  ref = Get_cs ();

When an rvalue is pointed to by the Const reference, its life cycle is extended, and this usage I mentioned in a previous blog about its application, click here.

The hidden logic here is that the right value cannot be converted directly to an lvalue (but the left value can be converted to the right value).

These two features are mentioned above:

1) allow calling member functions.

2) can only be pointed by the const reference.

Leads to some more interesting results, such as:

void func (cs& c) {   "C:" << c.get_i () << Endl;} //Errorfunc (Get_cs ());  correct func (get_cs () = Get_cs ());         

Where: Func (get_cs () = Get_cs ()), the correct reason is that the member function of CS operator= () returns cs&!

Not allowing non-const reference reference rvalue is not perfect, it actually raises some problems, such as the interface of the copy constructor is inconsistent, what does it mean?

Class cs{public    :              operator= (const cs& c);}; // Another notation class publicoperator= (cs2& c);};        

The difference between the above two formulations is the parameter, a const reference, a non-const.

In general, if you do not need to modify the passed in parameters, we tend to press the const reference, but for copy constructor, it is often necessary to modify the parameters of the value, such as auto_ptr.

similar to Auto_ptrclass auto_ptr{public   : auto_ptr (auto_tr& p) {ptr_ = p.ptr_; p.ptr_ =privatevoid* ptr_;};         

Therefore, for auto_ptr, its copy constructor parameter is non const reference.

This kind of writing should have been encouraged, non const reference is more flexible than the const reference to cope with various situations, thus maintaining a consistent interface type.

However, if the copy constructor is written like this, but the use of rvalue has brought a great deal, as the previous example, rvalue can not be referenced by non const reference, so a copy like auto_ptr Constructor can not be passed into rvalue.

error auto_ptr p (get_ptr ());  operator= () in the same vein, wrong. Auto_ptr p = get_ptr ();   

This is one of the reasons why auto_ptr is very difficult to use.

To solve this problem, a new reference type is introduced in C++11, which is designed to point to rvalue, with this new type, where the reference types of Lvalue and rvalue are distinguished from each other in c++11, before they are the same.

Because of this new type, it leads to the new semantics in C++11, move (), Forward (), and so on, where we sell a xiaoguanzi first, we'll talk about it next time.

[Reference]

http://accu.org/index.php/journals/227

Left and right values in C + +

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.