The difference between pointer and reference.

Source: Internet
Author: User
Tags constant definition

From: http://blog.csdn.net/listening_music/article/details/6921608

The following is a brief introduction:

  • Pointer-for a type T, T * is the pointer type pointing to T, that is, a T * type variable can save the address of a t object, type t can be added with some restrictions, such as const and volatile. See the following figure for pointer meanings:

  • Reference-a reference is an alias of an object. It is mainly used for function parameters and return value types. The symbol X & indicates a reference of the X type. See, for the meaning of the reference:

2. Differences between pointers and references
  • First, the reference cannot be null, but the pointer can be null. As mentioned above, the reference is the alias of an object, and the reference is null. -- the object does not exist. How can I have an alias! Therefore, Initialization is required when defining a reference. Therefore, if you have a variable that is used to point to another object, but it may be null, you should use a pointer. If the variable always points to an object. E ., variables cannot be empty in your design. You should use references. For example, if a reference variable is defined, the compilation will fail if it is not initialized (an error occurs during compilation ):

    The declared pointer can not point to any object. It is precisely for this reason that,The pointer must be empty before it can be used..

  • Second, the reference cannot change the direction of an object, but the pointer can change and point to other objects. Note: although the reference cannot change the point, it can change the content of the initialization object. For example, for a ++ operation, the referenced operation directly reflects the object to which it points, rather than changing the point. The operation on the pointer will direct the pointer to the next object, instead of changing the content of the object. See the following code:

    # Include <iostream>

    Using namespace STD;

     

    Int main (INT argc, char ** argv)

    {

    Int I = 10;

    Int & ref = I;

    Ref ++;

    Cout <"I =" <I <Endl;

    Cout <"ref =" <ref <Endl;

    Int J = 20;

    Ref = J;

    Ref ++;

    Cout <"I =" <I <Endl;

    Cout <"ref =" <ref <Endl;

    Cout <"J =" <j <Endl;

    Return 0;

    }

    The ++ operation on Ref directly reflects the variable to be referred to, and reassigns "ref = J" to the referenced variable ref, which does not change the direction of ref. It still points to I, instead of J. Of course, performing the ++ operation on the ref will not affect J. If these are pointers, the situations are very different. Please experiment on your own. The output result is as follows:

  • Again, the reference size is the size of the variable pointed to, because the reference is just an alias; the pointer is the size of the pointer, 4 bytes. See:

    We can also see from the above:References are more beautiful than pointers. You can use reference variable names between referenced content instead of pointer content *; when defining a reference, you do not need to use & access like a pointer.

  • Finally, the reference is safer than the pointer. Since there is no null reference, and the reference is initialized to point to an object, it cannot be changed to another object reference, so the reference is safe. A pointer can point to another object at any time without being initialized or null, so it is not safe. Although the const pointer cannot be changed, there is still a null pointer, and it may generate a wild pointer (that is, multiple pointers direct to a memory, after one pointer is free, other pointers become wild pointers ).

All in all, in short, all these differences can be attributed"The Pointer Points to a piece of memory. Its content refers to the memory address, and the reference is the alias of a piece of memory. The reference does not change to the point."

3. Special const

Why should I mention the const keyword here? Because const imposes different limitations on pointers and references, let me see them one by one.

  • Constant pointer vs constant reference

Constant pointer: a pointer to a constant. Add const before the type of the pointer Definition Statement to indicate that the object to which the pointer is a constant.

Defining a pointer to a constant only limits the indirect access operation of the pointer, but does not specify the Operation Specifications of the value itself pointed to by the pointer.

The constant pointer definition "const int * pointer = & A" tells the compiler that * pointer is a constant and cannot operate * pointer as the left value.

Constant reference: refers to the reference of a constant. Add const before the type of the referenced Definition Statement to indicate that the object pointing to is a constant. Just like pointers, you cannot use references to re-assign values to variables.

  • Pointer constant vs reference constant

Add const before the pointer name of the pointer Definition Statement to indicate that the pointer itself is a constant. Initialization is required when defining pointer constants! This is a natural attribute for reference. You do not need to reference the reference name of the pointer Definition Statement before adding Const.

The pointer constant definition "int * const pointer = & B" tells the compiler that pointer is a constant and cannot be operated as the left value. However, indirect access values can be modified, that is, * pointer can be modified.

  • Constant pointer constant vs constant reference constant

Constant pointer constant: A pointer constant pointing to a constant. You can define a pointer constant pointing to a constant. It must be initialized during definition. The constant pointer constant definition "const int * const pointer = & C" tells the compiler that both pointer and * pointer are constants and cannot be operated as left values.

The so-called "constant reference constant" does not exist, because the reference variable is a reference constant just as mentioned above. C ++ does not distinguish between the const reference of a variable and the reference of a const variable. The program must not assign a value to the reference itself to direct it to another variable. Therefore, the reference is always Const. If the reference application keyword const is used, the target is called the const variable. No: const double const & A = 1; only const double & A = 1;

Conclusion: There is a rule that can distinguish whether const modifies the pointer or the data pointed to by the pointer-draw an asterisk (*) Vertically passed through the pointer declaration. If const appears on the left, the Pointer Points to a constant. If the const appears on the right, the pointer itself is a constant. The reference itself is a constant, that is, it cannot be changed.

4. Implementation of pointers and references

We use the following simple code to analyze pointers and references in depth:

# Include <iostream>

Using namespace STD;

 

Int main (INT argc, char ** argv)

{

Int I = 1;

Int & ref = I;

Int x = ref;

Cout <"X is" <x <Endl;

 

Ref = 2;

Int * P = & I;

Cout <"ref =" <ref <", I =" <I <Endl;

}

Use the above CodeG ++ test. cCompile and decompileObjdump-d a. OutTo obtain the assembly code of the main function:

08048714 <main>:

8048714: 55 push % EBP

8048715: 89 E5 mov % ESP, % EBP

8048717: 83 E4 F0 and $0xfffffff0, % ESP // reserved location of main function parameters argc and argv

80100001a: 56 push % ESI

80100001b: 53 push % EBX

80100001c: 83 EC 28 sub $0x28, % ESP

80100001f: C7 44 24 1C 01 00 00 movl $0x1, 0x1c (% ESP) // save 0 X1 to the ESP register, that is, int I = 1

8048726: 00

8048727: 8d 44 24 1C Lea 0x1c (% ESP), and the address of variable I in % eax // ESP register is sent to eax

80100002b: 89 44 24 18 mov % eax, 0x18 (% ESP) // pass the content (I address) in the register eax to the variable ref in the register, that is, Int & ref = I

804872f: 8B 44 24 18 mov 0x18 (% ESP), % eax // pass the ref in the register ESP to eax, that is, the address of I

8048733: 8B 00 mov (% eax), % eax // take the value in the register eax as the address and obtain the value to eax 8048735: 89 44 24 14 mov % eax, 0x14 (% ESP) // pass the value in register eax to X in register ESP, that is, x = ref

8048739: C7 44 24 04 00 89 04 movl $0x8048900,0x4 (% ESP)

8048740: 08

8048741: C7 04 24 40 A0 04 08 movl $0x804a040, (% ESP)

8048748: E8 CB Fe FF call 8048618 <_ zstlsist11char_traitsiceerst13basic_ostreamict_es5_pk@ PLT>

803664d: 8B 54 24 14 mov 0x14 (% ESP), % edX

8048751: 89 54 24 04 mov % edX, 0x4 (% ESP)

8048755: 89 04 24 mov % eax, (% ESP)

8048758: E8 5B Fe FF call 80485b8 <_ znsolsei @ PLT>

804875d: C7 44 24 04 38 86 04 movl $0x8048638,0x4 (% ESP)

8048764: 08

8048765: 89 04 24 mov % eax, (% ESP)

8048768: E8 BB Fe FF call 8048628 <_ znsolsepfrsos_e @ PLT> // from 8048739 ~ 8048768 these rows are executed by "cout <" X is "<x <Endl ;"

80100006d: 8B 44 24 18 mov 0x18 (% ESP), % eax // pass the ref in the register ESP to eax

8048771: C7 00 02 00 00 00 movl $0x2, (% eax) // save 0x2 to the eax register

8048777: 8d 44 24 1C Lea 0x1c (% ESP), and the address of variable I in % eax // ESP register is sent to eax

804877b: 89 44 24 10 mov % eax, 0x10 (% ESP) // transfer the content in register eax (that is, the address of I) to P in register ESP

804877f: 8B 5C 24 1C mov 0x1c (% ESP), % EBX

8048783: 8B 44 24 18 mov 0x18 (% ESP), % eax

8048787: 8B 30 mov (% eax), % ESI

8048789: C7 44 24 04 06 89 04 movl $0x8048906,0x4 (% ESP)

8048790: 08

8048791: C7 04 24 40 A0 04 08 movl $0x804a040, (% ESP)

8048798: E8 7b Fe FF call 8048618 <_ zstlsist11char_traitsiceerst13basic_ostreamict_es5_pk@ PLT>

804879d: 89 74 24 04 mov % ESI, 0x4 (% ESP)

80347a1: 89 04 24 mov % eax, (% ESP)

80366a4: E8 0f Fe FF call 80485b8 <_ znsolsei @ PLT>

80366a9: C7 44 24 04 0d 89 04 movl $ 0x804890d, 0x4 (% ESP)

80366b0: 08

8010000b1: 89 04 24 mov % eax, (% ESP)

80366b4: E8 5f Fe FF call 8048618 <_ zstlsist11char_traitsiceerst13basic_ostreamict_es5_pk@ PLT>

80366b9: 89 5C 24 04 mov % EBX, 0x4 (% ESP)

80366bd: 89 04 24 mov % eax, (% ESP)

80366c0: E8 F3 fd ff call 80485b8 <_ znsolsei @ PLT>

80366c5: C7 44 24 04 38 86 04 movl $0x8048638,0x4 (% ESP)

80366cc: 08

8010000cd: 89 04 24 mov % eax, (% ESP)

80366d0: E8 53 Fe FF call 8048628 <_ znsolsepfrsos_e @ PLT> // these rows are executed "cout <" ref = "<ref <", I = "<I <Endl ;"

8010000d5: B8 00 00 00 00 mov $0x0, % eax

8010000da: 83 C4 28 add $0x28, % ESP

8010000dd: 5B pop % EBX

80366de: 5E pop % ESI

8010000df: 89 EC mov % EBP, % ESP

8010000e1: 5D pop % EBP

80366e2: C3 RET

From the assembly code, we can see that the implementation of pointers and references in the compiler is the same:

  • Reference Int & ref = I; 

8048727: 8d 44 24 1C Lea 0x1c (% ESP), % eax//The address of variable I in the ESP register is sent to eax.

803662b: 89 44 24 18 mov % eax, 0x18 (% ESP)// Pass the content (the address of I) in the register eax to the variable ref in the register, that is, Int & ref = I

  • Pointer int * P = & I;

8048777: 8d 44 24 1C Lea 0x1c (% ESP), % eax// Send the address of variable I in the ESP register to eax

804877b: 89 44 24 10 mov % eax, 0x10 (% ESP)// Transfer the content in register eax (that is, the address of I) to P in register ESP

Although pointers and references are implemented in the compilation process, the reference format is much more convenient and secure. Some people say :"A reference is just an alias and does not occupy memory space?"We can reveal this lie through this fact! In fact, references also occupy memory space.

5. pointer transfer and reference Transfer

To better understand pointers and references, we will introduce pointer passing and reference passing. How does a pointer and Reference Function Pass values? (The following section referencesDifferences Between Reference transfer and pointer transfer in C ++ (further sorting))

  • A pointer passing parameter is essentially a value passing method, which transmits an address value. During the value transfer process, parameters in the form of the called function are processed as local variables of the called function, that is, the memory space is opened in the stack to store the values of the real parameters put in by the main function, it becomes a copy of the real parameter. The feature of value transfer is that any operation of the form parameter of the called function is performed as a local variable, without affecting the value of the real parameter variable of the main function.
  • During the reference transfer process, the form parameter of the called function is also used as a local variable to open up the memory space in the stack, but the address of the real parameter variable stored by the main function is stored. Any operation of the called function on the form parameter is processed as indirect addressing. That is, the address stored in the stack is used to access the real variable in the main function. Because of this, any operation performed by the called function on the form parameter affects the real parameter variables in the main function.

Reference transfer and pointer transfer are different, although they are all a local variable in the space of the called function stack, however, any processing of referenced parameters will operate the relevant variables in the main function in an indirect addressing method. If you change the pointer address in the called function for pointer passing parameters, it will not affect the variables related to the main function. If you want to change the relevant variables in the main function by passing the pointer parameter, you must use a pointer to the pointer or pointer reference.

 

In terms of concept. Essentially, a pointer is a variable that stores the variable address. It is logically independent and can be changed, this includes changes to the address it points to and the data stored in the address it points.

Reference is an alias. It is not logically independent and its existence is dependent. Therefore, the reference must be initialized at the beginning, in addition, the referenced object cannot be changed throughout its lifecycle (it can only be attached to the same variable from start to end ).

In C ++, pointers and references are often used to pass function parameters. However, pointer passing parameters are essentially different from reference passing parameters:

A pointer passing parameter is essentially a value passing method, which transmits an address value. During the value transfer process, parameters in the form of the called function are processed as local variables of the called function, that is, the memory space is opened in the stack to store the values of the real parameters put in by the main function, it becomes a copy of the real parameter. The feature of value transfer is that any operation of the form parameter of the called function is performed as a local variable, without affecting the value of the real parameter variable of the main function. (The address value of the real parameter pointer will not change here)

During the reference transfer process, the form parameters of the called functions, although also opened up the memory space in the stack as local variables, however, the address of the Real Variable put in by the main function is stored. Any operation of the called function on the form parameter is processed as indirect addressing. That is, the address stored in the stack is used to access the real variable in the main function. Because of this, any operation performed by the called function on the form parameter affects the real parameter variables in the main function.

Reference transfer and pointer transfer are different, although they are all a local variable in the space of the called function stack, however, any processing of referenced parameters will operate the relevant variables in the main function in an indirect addressing method. If you change the pointer address in the called function for pointer passing parameters, it will not affect the variables related to the main function. If you want to change the relevant variables in the main function by passing the pointer parameter, you must use a pointer to the pointer or pointer reference.

To further deepen the differences between pointers and references, I will explain the differences between them from the compilation perspective:

During compilation, the program adds pointers and references to the symbol table, respectively. The symbol table records the variable name and the address corresponding to the variable. The address value corresponding to the pointer variable in the symbol table is the address value of the pointer variable, and the address value referenced in the symbol table is the address value of the referenced object. The symbol table will not be changed after it is generated, so the pointer can change the object to which it points (the value in the pointer variable can be changed), but the referenced object cannot be modified.

Finally, we will summarize the similarities and differences between pointers and references:

★Similarities:

● All are addresses;

The Pointer Points to a piece of memory. Its content refers to the memory address, and the reference is the alias of a piece of memory.

★Differences:

● A pointer is an entity, and a reference is only an alias;

● The reference can only be initialized once during definition, but cannot be changed afterwards; the pointer can be changed; the reference can be "from one end", and the pointer can be "Thinking Differently ";

● Reference has no const, pointer has const, and const pointer is immutable; (specifically, there is no Int & Const A, while const Int & A has, the former guidance itself means that the alias cannot be changed. This is of course, so this form is not required. The value indicated by the latter guidance cannot be changed)

● The reference cannot be blank or the pointer can be blank;

● "Sizeof reference" gets the size of the variable (object) pointed to, while "sizeof Pointer" gets the size of the pointer;

● Pointer and reference auto-increment (++) operations have different meanings;

● The reference is type-safe, but the pointer is not (the reference has more type checks than the pointer

 

 

I. Concepts of reference

Reference introduces a synonym for an object. The expression of the definition reference is similar to the definition pointer, but it is replaced *.
Example: Point pt1 (10, 10 );
Point & pt2 = pt1; defines a reference where pt2 is pt1. With this definition, pt1 and pt2 indicate the same object.
It is important to note that references do not generate copies of objects, but are only synonyms of objects. Therefore, after the current statement is executed:
Pt1.offset (2, 2 );
Both pt1 and pt2 have (12, 12) values.
The reference must be initialized immediately during definition because it must be a synonym for something. You cannot define a reference before
Initialize it. For example, the following statement is invalid:
Point & pt3;
Pt3 = pt1;
So what is the purpose of referencing a synonym for something?
The following two main purposes of reference are discussed: as a function parameter and return the left value from the function.

Ii. Reference parameters

1. Passing variable parameters
In traditional C, parameters are passed through values when a function is called, which means that the function parameters do not have the ability to return values.
Therefore, in traditional C, if function parameters are required to have the ability to return values, they are usually implemented through pointers. For example
The C program for the exchange of two integer values is as follows:
Void swapint (int * a, int * B)
{
Int temp;
Temp = *;
A = * B;
* B = temp;
}

After the reference mechanism is used, the C ++ version of the above program is:
Void swapint (Int & A, Int & B)
{
Int temp;
Temp =;
A = B;
B = temp;
}
The C ++ method that calls this function is: swapint (x, y); C ++ automatically transmits the address of X and Y to the swapint function as a parameter.

2. Passing large objects to Functions
When a large object is passed to a function, the parameter transfer efficiency can be improved by using reference parameters, because reference does not produce
Copy, that is, when the parameter is passed, the object does not need to be copied. The following example defines a class with a finite Integer Set:
Const maxcard = 100;
Class Set
{
Int elems [maxcard]; // The element in the set. maxcard indicates the maximum number of elements in the set.
Int card; // The number of elements in the set.
Public:
Set () {card = 0;} // Constructor
Friend set operator * (set, set); // reload operator number *, used to calculate the intersection of a set, using an object as a value passing Parameter
// Friend set operator * (set &, set &) overload operator number *, used to calculate the intersection of sets and use the object reference as the value passing Parameter
...
}
First consider the implementation of set intersection
Set operator * (set set1, set set2)
{
Set res;
For (INT I = 0; I <set1.card; ++ I)
For (Int J = 0; j> set2.card; ++ J)
If (set1.elems [I] = set2.elems [J])
{
Res. elems [res. Card ++] = set1.elems [I];
Break;
}
Return res;
}
Since the overload operator cannot operate the pointer independently, we must declare the number of operations as the set type rather than set *.
When * is used for intersection operations, the entire set is copied, which is very inefficient. We can use references to avoid this situation.
Set operator * (set & set1, set & set2)
{Set res;
For (INT I = 0; I <set1.card; ++ I)
For (Int J = 0; j> set2.card; ++ J)
If (set1.elems [I] = set2.elems [J])
{
Res. elems [res. Card ++] = set1.elems [I];
Break;
}
Return res;
}

Iii. Reference return values

If a function returns a reference, the function call can also be assigned a value. Here is a function that has two reference parameters and returns a double-precision reference:
Double & MAX (double & D1, double & D2)
{
Return D1> D2? D1: D2;
}
Because the max () function returns a reference to the Double Precision number, we can use max () to add 1 to the large double precision number:
Max (x, y) + = 1.0;

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.