The following is an overview of what you can say in plain words:
- Pointers-For a type t,t* is a pointer to T type, that is, a variable of type t* can hold the address of a T object, and type T can add some qualifiers, such as const, volatile and so on. See, the meaning of the pointer shown:
- Reference-a reference is an alias for an object that is used primarily for function arguments and return value types, and the symbol x& represents a reference of type X. See, the meaning of the reference shown:
2. The difference between a pointer and a reference
- First, the reference cannot be empty, but the pointer can be empty. As mentioned earlier, the reference is an alias of the object, the reference is empty--the object does not exist, how can there be an alias! Therefore, when defining a reference, it must be initialized. So if you have a variable that is used to point to another object, but it may be empty, then you should use a pointer, if the variable always points to an object, i.e., your design does not allow variables to be empty, you should use references. For example, if you define a reference variable and do not initialize it, the compilation will not pass (compile-time error):
The declaration pointer is not directed to any object, and it is for this reason that a null operation must be done before the pointer is used, and the reference is not necessary .
- Second, the reference can not be changed to point to an object "to the death", but the pointer can be changed to point to other objects. Description: Although the reference cannot be changed to point to, it can change the contents of the initialized object. For example, in the case of the + + operation, the action on the reference directly responds to the object pointed to, not to the point, whereas the manipulation of the pointer causes the pointer to point to the next object instead of changing the contents of the object being referred to. 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 is a direct reaction to the indicated variable, and the reference variable ref re-assigns the value "Ref=j", does not change the point of ref, it still points to I, not J. As a matter of course, the + + operation on ref does not affect J. And these are the pointers, the situation is very different, please do your own experiment. The output results are as follows:
- Again, the size of the reference is the size of the variable you are pointing to, because the reference is just an alias; the pointer is the size of the pointer itself, 4 bytes. See the following:
As can be seen from the above: references are more beautiful than pointers, and references to content can be used to refer to variable names instead of using * as pointers, and to define references without using & access as pointers.
- Finally, references are more secure than pointers. Because there is no null reference, and once the reference is initialized to point to an object, it cannot be changed to a reference to another object, so the reference is safe. For pointers, it can point to other objects at any time, and may not be initialized, or null, so it is unsafe. The const pointer cannot be changed to point, but there is still a null pointer, and it is possible to produce a wild pointer (that is, multiple pointers point to a piece of memory, and after a free pointer, the other pointer becomes a wild pointer).
All in all, in short--all of these differences can be attributed to the pointer pointing to a piece of memory whose content is the address of the referred memory, whereas the reference is the alias of a block of memory, and the reference does not change the point. "
3. Special Place const
Why should I mention the const keyword here? Because the const has a different qualification for pointers and references, let's hear my one by one coming.
- Constant pointer vs constant reference
Constant pointer: A pointer to a constant that is const before the type of the pointer definition statement, indicating that the object being pointed to is a constant.
A pointer to a constant restricts only the indirect access operation of the pointer, not the operation of the value itself pointed to by the pointer.
The constant pointer defines "const int* Pointer=&a" to tell the compiler that *pointer is a constant and cannot manipulate *pointer as an lvalue.
Constant reference: a reference to a constant that is const before the type of the reference definition statement, indicating that the object being pointed to is a constant. As with pointers, you cannot use references to reassign a pointer to a variable.
- Pointer constant vs Reference constant
Adds a const to the pointer name of the pointer definition statement, indicating that the pointer itself is a constant. Must be initialized when defining pointer constants! This is a reference to a property that is inherently referenced, and does not have to refer to the pointer definition statement before the reference name plus Const.
The pointer constant defines "int* const pointer=&b" to tell the compiler that pointer is a constant and cannot operate as an lvalue, but allows for modification of the indirect access value, that is, *pointer can be modified.
- Constant pointer constant vs constant reference constant
Constant pointer constant: A pointer constant pointing to a constant that defines a pointer constant to a constant that must be initialized when defined. Constant pointer constants define "Const int* const POINTER=&C" to tell the compiler that pointer and *pointer are constants, and they cannot operate as lvalue values.
There is no so-called "constant reference constant" because the reference variable is the reference constant as mentioned above. C + + does not differentiate between a const reference to a variable and a reference to a const variable. A program should never reassign a reference to another variable, so the reference is always const. If you apply the keyword const to a reference, the effect is to make its target a const variable. That is, no: const double const& a=1; only const double& a=1;
Summary: There is a rule that makes it very well to distinguish whether const is a modifier pointer, or the data that the pointer points to-draw a vertical asterisk (*) through the pointer declaration, if the const appears to the left of the line, the pointer to the data is a constant, if the const appears on the right, the pointer itself is a constant. and the reference itself and the sky is the constant, that is, can not change the point.
4. Implementation of pointers and references
We use the following simple code to drill down on pointers and references:
#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;
}
The above code is compiled with g++ test.c , and then disassembled objdump-d a.out, to get the assembly code of the main function as follows:
08048714 <main>: 8048714:55 Push%EBP 8048715:89 e5 mov%esp,%ebp 8048717:83 e4 F0 and $0xfffffff0,%esp//is the parameter argc, argv reserved position for the main function 804871A:56 Push%esi 804871b:53 Push%EBX 804871c:83 EC $0x28,%esp Sub 804871F:C7 1c MOVL $0X1,0X1C (%ESP)//Save 0x1 in ESP register, int i=1 8,048,726:00
8048727: 8d 44 24 1c lea 0x1c(%esp),%eax// esp寄存器里的变量i的地址传给eax
804872b:89%eax,0x18 (%ESP)//The contents of the register EAX (the address of I) to the variable ref in the register, that is, int& ref=i 804872f:8b 0x18 (%ESP),%eax//the register in ESP to EAX, the address of I 8048733:8B (%eax),%eax//with the value of the register EAX as the address, remove the value to EAX 8048735:89 (%eax,0x14)///The value of the Register%ESP To the X in the register ESP, which is x=ref 8048739:c7 movl $0x8048900,0x4 (%ESP) 8,048,740:08 8048741:c7 A0 movl $0x804a040, (%ESP) 8048748:e8 CB FE FF FF call 8048618 <[email protected]> 804874D:8B mov 0x14 (%esp),%edx 8048751:89 mov%edx,0x4 (%ESP) 8048755:89 mov%eax, (%ESP) 8048758:e8 5b FE FF FF call 80485B8 <[email protected]> 804875d:c7 movl $0x8048638,0x4 (%ESP) 8,048,764:08 8048765:89 mov%eax, (%ESP) 8048768:E8 BB FE FF FF call 8048628 <[email protected]>//from 8048739~8048768 These lines are executed "cout<<" x is "<<x< ;<endl; " 804876d:8b 0x18 mov (%ESP),%eax//the register in ESP to EAX 8048771:c7 xx movl $0x2, (%EAX)//Save 0x2 to the EAX register 8048777:8D 1c Lea 0X1C (%ESP), the address of the variable i in the%eax//ESP register is passed to EAX 804877b:89%eax,0x10 (%ESP)//upload the contents of the register eax (that is, the address of I) to the P in the Register ESP 804877F:8B 5c 1c mov 0x1c (%ESP),%EBX 8048783:8b 0x18 mov (%ESP),%eax 8048787:8B mov (%eax),%esi 8048789:c7 movl $0x8048906,0x4 (%ESP) 8,048,790:08 8048791:c7 A0 movl $0x804a040, (%ESP) 8048798:e8 7b FE FF FF call 8048618 <[email protected]> 804879D:89 mov%esi,0x4 (%ESP) 80487A1:89 mov%eax, (%ESP) 80487a4:e8 0f FE FF FF call 80485B8 <[email protected]> 80487a9:c7 0d movl $0x804890d,0x4 (%ESP) 80487b0:08 80487B1:89 mov%eax, (%ESP) 80487b4:e8 5f FE FF FF call 8048618 <[email protected]> 80487b9:89 5c mov%ebx,0x4 (%ESP) 80487BD:89 mov%eax, (%ESP) 80487c0:e8 f3 FD ff FF call 80485B8 <[email protected]> 80487c5:c7 movl $0x8048638,0x4 (%ESP) 80487cc:08 80487CD:89 mov%eax, (%ESP) 80487d0:e8-FE FF FF call 8048628 <[email protected]>//These lines are executed "cout<<" ref = "<<ref<<", i = " <<i<<endl; " 80487d5:b8 xx xx $0x0,%eax 80487da:83 C4 Add $0x28,%esp 80487dd:5b Pop%EBX 80487de:5e Pop%esi 80487df:89 EC mov%ebp,%esp 80487E1:5D Pop%EBP 80487E2:C3 ret |
As you can see from the assembler code, the implementation of pointers and references in the compiler is actually the same:
8048727: 8d 44 24 1c lea 0x1c(%esp),%eax// esp寄存器里的变量i的地址传给eax
804872b:89%eax,0x18 (%ESP)//The contents of the register EAX (address of I) are passed to the variable ref in the register, i.e. int& ref=i
8048777:8d 1c Lea 0X1C (%ESP),the address of the variable i in the%EAX//ESP register is passed to EAX
804877b:89%eax,0x10 (%ESP) //upload the contents of the register eax (that is, the address of I) to the P in the Register ESP
Although pointers and references are eventually implemented in the same way in the compilation, the form of references is much easier to use and more secure. Some people say: "The reference is just an alias, does not occupy memory space?" "Through this fact we can debunk this lie!" In fact, references also occupy memory space.
5. Pointer passing and reference passing
To better understand pointers and references, let's look at pointer passing and reference passing. How do pointers and references function as functions to pass values? (The following paragraph references the difference between reference passing and pointer passing in C + + (further collation))
- A pointer pass parameter is essentially the way a value is passed, which is passed an address value. In the process of value passing, the formal parameters of the called function are treated as local variables of the modulated function, that is, the memory space is opened in the stack to hold the values of the arguments put in by the key function, thus becoming a copy of the argument. The characteristic of value passing is that any operation of the function on the formal parameter is done as a local variable, without affecting the value of the argument variable of the main key function.
- In the process of reference passing, the formal parameters of the called function also open up the memory space in the stack as a local variable, but the address of the argument variable that is put in by the key function is stored. Any operation of the modulated function on the formal parameter is handled as an indirect addressing, that is, the argument variables in the central Melody function are accessed through the address stored in the stack. Because of this, any action taken by the modulated function on the parameter affects the argument variables in the keynote function.
Reference passing and pointer passing are different, although they are a local variable on the function stack space, but any handling of reference parameters is handled by an indirection to the relevant variables in the key function. For pointers passing parameters, if you change the address of the pointer in the called function, it will not affect the relevant variable of the key function. If you want to change the related variable in the key function by passing the pointer parameter, you have to use a pointer to the pointer, or a pointer reference.
Conceptually speaking. A pointer is essentially a variable that holds the address of a variable, logically independent, and can be changed, including the change in the address it points to and the data stored in the address it points to.
Whereas a reference is an alias, it is logically not independent, its existence is dependent, so the reference must be initialized at the outset, and the object it refers to cannot be changed throughout its life cycle (it can only be attached to the same variable from beginning to end).
In C + +, pointers and references are often used for parameter passing of functions, however, pointer passing parameters and reference passing parameters are inherently different:
A pointer pass parameter is essentially the way a value is passed, which is passed an address value. In the process of value passing, the formal parameters of the called function are treated as local variables of the modulated function, that is, the memory space is opened in the stack to hold the values of the arguments put in by the key function, thus becoming a copy of the argument. The characteristic of value passing is that any operation of the function on the formal parameter is done as a local variable, without affecting the value of the argument variable of the main key function. (Here is the address value of the argument pointer itself will not change)
In the process of reference passing, the formal parameters of the called function also open up the memory space in the stack as a local variable, but the address of the argument variable that is put in by the key function is stored. Any operation of the modulated function on the formal parameter is handled as an indirect addressing, that is, the argument variables in the central Melody function are accessed through the address stored in the stack. Because of this, any action taken by the modulated function on the parameter affects the argument variables in the keynote function.
Reference passing and pointer passing are different, although they are a local variable on the function stack space, but any handling of reference parameters is handled by an indirection to the relevant variables in the key function. For pointers passing parameters, if you change the address of the pointer in the called function, it will not affect the relevant variable of the key function. If you want to change the related variable in the key function by passing the pointer parameter, you have to use a pointer to the pointer, or a pointer reference.
To further deepen the distinction between pointers and references, let me elaborate on the differences between them from a compilation perspective:
The program adds pointers and references to the symbol table at compile time, and the symbol table records the variable name and the corresponding address of the variable. The corresponding address value of the pointer variable on the symbol table is the address value of the pointer variable, and the corresponding address value on the symbol table refers to the address value of the Reference object. The symbol table does not change after it is generated, so the pointer can change the object it points to (the value in the pointer variable can be changed), and the reference object cannot be modified.
Finally, summarize the same points and different points of pointers and references:
★ Same point:
Are the concept of addresses;
The pointer points to a piece of memory whose contents are the address of the referred memory, and the reference is the alias of a block of memory.
★ Different points:
The pointer is an entity, and the reference is only an individual name;
References can only be initialized once at the time of definition, immutable, pointers variable, reference "mindedness", pointers "inconstant";
The reference does not have a const, the pointer has a const,const pointer is immutable, (specifically, there is no int& const a This form, and the const int& A is some, the former guideline with itself that alias can not be changed, which is of course, so do not need this form, the latter The guideline cannot be changed by the value of the reference)
The reference cannot be null, the pointer can be empty;
The "sizeof reference" gets the size of the variable (object) pointed to, and the "sizeof pointer" gets the size of the pointer itself;
Pointer and reference self-increment (+ +) operation has different meanings;
References are type-safe, while pointers are not (references are more type-checked than pointers
First, the concept of reference
The reference introduces a synonym for the object. Defining a reference is similar to defining a pointer, but using & instead of *. Example: Point pt1 (10,10); Point &pt2=pt1; A reference to PT1 is defined for pt2. With this definition, PT1 and pt2 represent the same object. It is particularly emphasized that a reference does not produce a copy of the object, just a synonym for the object. Therefore, when the following statement executes: Pt1.offset (2,2); Both PT1 and pt2 have a value of (12,12). A reference must be initialized as soon as it is defined, because it must be a synonym for something. You cannot define a reference before Initialize it. For example, the following statement is illegal: Point &pt3; PT3=PT1; So since the reference is just a synonym for something, what is its use? The following is a discussion of the two main uses of a reference: as a function parameter and return an lvalue from a function.
Second, reference parameters
1. Passing Variable parameters In traditional C, a function is passed by value when called, which means that the function's arguments do not have the ability to return a value. So in the traditional C, if the function parameter has the ability to return a value, it is often implemented by pointers. For example, to implement The C program for exchanging two integer variable values is as follows: void Swapint (int *a,int *b) { int temp; Temp=*a; A=*b; *b=temp; }
After using the reference mechanism, the C + + version of the above program is: void Swapint (int &a,int &b) { int temp; Temp=a; A=b; B=temp; } The C + + method that calls the function is: Swapint (x, y); C + + automatically passes the address of X, y as an argument to the Swapint function.
2. Passing large objects to functions When large objects are passed to a function, reference parameters can be used to improve the efficiency of parameter passing because the reference does not produce the object's The copy, which is the parameter passing, does not need to be copied. The following example defines a class for a finite set of integers: Const MAXCARD=100; Class Set { int Elems[maxcard]; Sets and elements in Maxcard that represent the maximum number of elements in the collection. int card; The number of elements in the collection. Public Set () {card=0;}//constructor Friend set operator * (set, set); Overloaded operation symbol *, used to calculate the intersection of a set using an object as a pass-value parameter Friend Set operator * (Set &, set &) overloaded operation symbol *, used to calculate the intersection of the set with the object's reference as a pass-value parameter ... } Consider the implementation of set intersection first 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; } Because overloaded operators cannot operate on pointers alone, we must declare the operands as set type instead of Set *. The entire collection is duplicated every time the intersection is used, so it is 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; }
Third, reference return value
If a function returns a reference, the call to that function can also be assigned a value. Here is a function that has two reference parameters and returns a reference to a double-precision number: Double &max (double &d1,double &d2) { Return d1>d2?d1:d2; } Since the max () function returns a reference to the double precision number, we can use Max () to add 1 to the larger double: Max (x, y) +=1.0; |
C Language Learning Note (002)-the difference between references and pointers in C + + (reproduced)