I. Basic knowledge
How pointers and references are declared:
Declaration pointer: char* PC;
Declaration reference: Char c = ' A '
char& rc = c;
The difference between them:
① from the perspective of the phenomenon, the pointer can change the value it points to at run time, and the reference will not change once it is bound to an object. This sentence can be understood as: The pointer can be assignable to point to another different object. However, references always point to objects that are specified when initialized and cannot be changed later, but the contents of the specified object can be changed.
② from memory allocation, the program allocates the memory area for the pointer variable instead of allocating the memory area for the reference, because the reference declaration must be initialized to point to an existing object. A reference cannot point to a null value.
③ from the compile point of view, 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, while the corresponding address value on the symbol table refers to the address value of the referenced object. The symbol table is not changed after it is built, so the pointer can change the object to which it is pointing (the value in the pointer variable can be changed), and the referenced object cannot be changed. This is the main reason to use referential security with pointers that are unsafe. In a sense, a reference can be considered a pointer that cannot be changed.
④ The fact that a reference to a null value does not exist means that the code that uses the reference is more efficient than using the pointer. Because you do not need to test the legality of a reference before using it. Instead, the pointer should always be tested to prevent it from being empty.
⑤ Theoretically, there is no limit to the series of pointers, but references can only be one level.
As follows:
Copy Code code as follows:
int** P1; Legal. Pointer to pointer
int*& P2; Legal. Reference to Pointer
int&* P3; Illegal. The pointer to the reference is illegal
int&& P4; Illegal. Reference to reference is illegal
Note that the above reading method is from left to right.
Program 1:
Copy Code code as follows:
#include "stdio.h"
int main (void)
{
Declares a char pointer pc and lets it point to a null value
char* pc = 0;
char a = ' a ';
Declare a reference RC and let it refer to the variable a
char& rc = A;
printf ("%d,%c\n", PC, RC);
Char *PC2;
Declares a pointer, but can not initialize the
PC2 = PC;
char& RC2;
When the above statement compiles, the following error occurs:
Error C2530: ' RC2 ': references must be initialized
That is, the application must initialize
rc = *pc;
The above statement compiles without problems, but when run, the following error is reported:
"0x00000000" Memory referenced by the "0x00401057" directive. The memory cannot be "read"
Description references cannot point to null values under any circumstances
return 0;
}
Program 2:
Copy Code code as follows:
#include <iostream>
#include <string>
using namespace Std;
int main (void)
{
String S1 ("Hello");
String S2 ("World");
printf ("%s\n", S1); You can't output S1 with printf, but you should use cout
cout << "S1 address =" << &s1 << endl;//&s1 = 0012ff64
cout << "s2 address =" << &s2 << endl;//&s2 = 0012ff54
string& rs = s1; 1. Define a reference Rs,rs reference S1
cout << "Reference rs address =" << &rs << Endl; &rs = 0012ff64
string* PS = &s1; Define a pointer PS, PS point to S1
cout << "pointer ps address =" << ps << endl;//PS = 0012ff64
cout << rs << "," << *ps << Endl; Hello, hello
If there is no #include <string>, the following error occurs when compiling the above statement:
Error c2679:binary ' << ': no operator defined which takes a right-
Hand operand of type ' class Std::basic_string<char,struct
Std::char_traits<char>,class std::allocator<char> > '
(or there is no acceptable conversion)
rs = s2; 2. RS still quotes S1, but S1 is now "world".
PS = &s2; PS Now points to S2
cout << "Reference rs address =" << &rs << Endl; &rs = 0012ff64 Unchanged
cout << "Reference rs value =" << rs << Endl; rs = "World" has changed
cout << "pointer ps address =" << ps << endl;//PS = 0012ff54 changed
cout << "Pointer PS refers to the content of the address =" << *ps << Endl; *ps = world has changed
cout << "S1 's address =" << &s1 << endl;//3. &S1 = 0012ff64 Unchanged
cout << "S1 value =" << s1 << Endl; 4. S1 = world has changed
return 0;
}
It may be considered that:
A reference is an alias for a variable that is determined when the reference is initialized, and cannot be changed again. See the bold word statement in program 2. The 1th sentence, declared RS reference s1,s1 value is "Hello", since then, RS is actually equivalent to the variable S1, or in a more essential sense, RS address is initialized when the S1 address, will not change again. This should be better understood, such as we defined a variable A in the program, no matter how we give a value, but its address will not change;
In the 2nd sentence, RS still points to the S1 address at initialization time, but the assignment here is equivalent to S1 assignment, so we can see from the 3rd and 4th sentences that the S1 address has not changed, but the value has changed.
Second, as a parameter transmission
Using this attribute of reference, it can be used as an outgoing parameter of a function. If program 3:
Copy Code code as follows:
#include <iostream>
#include <string>
using namespace Std;
int newevaluation (string& aStr)
{
String BStr ("Hello,");
ASTR = BStr + aStr;
return 0;
}
int main (void)
{
String AStr ("patrick!");
Newevaluation (ASTR);
Std::cout << aStr << Endl; Output result: "Hello, patrick!"
return 0;
}
A generic variable, however, cannot be passed from within a function, such as program 4:
Copy Code code as follows:
#include <iostream>
#include <string>
using namespace Std;
int newevaluation (String aStr)
{
String BStr ("Hello,");
ASTR = BStr + aStr;
return 0;
}
int main (void)
{
String AStr ("patrick!");
Newevaluation (ASTR);
Std::cout << aStr << Endl; Output result: "patrick!", Astr value unchanged
return 0;
}
Of course, program 3 can also be referred to as the way the pointer passes, such as program 5:
Copy Code code as follows:
#include <iostream>
#include <string>
using namespace Std;
int newevaluation (string* const ASTR)
{
String BStr ("Hello,");
*astr = BStr + *astr;
return 0;
}
int main (void)
{
String AStr ("patrick!");
Newevaluation (&ASTR);
Std::cout << aStr << Endl; Output result: "Hello, patrick!"
return 0;
}
Note the traps in the program, such as program 6:
Copy Code code as follows:
#include <iostream.h>
int *ppointer;
void SomeFunction ()
{
int nnumber;
Nnumber = 25;
Let the pointer point to Nnumber
Ppointer = &nNumber;
}
void Main ()
{
SomeFunction ()//To Ppointer assignment
Why did it fail here? Why not get 25
cout << "Value of *ppointer:" << *ppointer << Endl;
}
The program first calls the Somefunction function, creates a variable called Nnumber, and then lets the pointer ppointer point to it. But where is the problem? When the function is finished, the Nnumber is erased because of this local variable. A local variable is automatically deleted by the system after the function that defines it is executed. That is, when the Somefunction function returns the main function main (), the variable has been deleted, but Ppointer also refers to the area where the variable has been used but is now not part of the program.
Although the so-called dynamic allocation of memory is used in somefunction. Traps also exist in program 7:
Copy Code code as follows:
#include <iostream.h>
int *ppointer;
void SomeFunction ()
{
int intnumber = 25;
Let the pointer point to a new integral type
Ppointer = new int;
Ppointer = &intNumber;
}
void Main ()
{
SomeFunction (); Assigning Values to Ppointer
cout<< "Value of *ppointer:" << *ppointer << Endl;
Delete Ppointer;
}
As mentioned above, Intnumber's scope is limited to somefunction, leaving the somefunction, then intnumber does not exist, then &intnumber the address of the intnumber becomes meaningless , so the value that the address points to is indeterminate. If you change to the following program, there will be no problem.
Program 8:
Copy Code code as follows:
#include <iostream.h>
int *ppointer;
void SomeFunction ()
{
int intnumber = 25;
Let the pointer point to a new integral type
Ppointer = new int (intnumber);
}
void Main ()
{
SomeFunction (); Assigning Values to Ppointer
cout<< "Value of *ppointer:" << *ppointer << Endl;
Delete Ppointer;
}
Third, the pointer pointer
As I said before, the pointer is not a series limit.
Program 9:
Copy Code code as follows:
#include <stdio.h>
#include <stdlib.h>
void Main (void)
{
int I, J;
int a[10], b[3][4], *P1, *P2, **P3;
for (i = 0; i < i++)
scanf ("%d", &a[i]);
for (i = 0; i < 3; i++)
for (j = 0; J < 4; J + +)
scanf ("%d", &b[i][j]);
P1 = A;
P3 = &p1;
for (i = 0; i < i++)
printf ("%4d", * (*p3+i));
printf ("\ n");
for (P1 = A; p1-a < p1++)
{
P3 = &p1;
printf ("%4d", **P3);
}
printf ("\ n");
for (i = 0; i < 3; i++)
{
P2 = b[i];
P3 = &p2;
for (j = 0; J < 4; J + +)
printf ("%4d", * (*P3+J));
printf ("\ n");
}
for (i = 0; i < 3; i++)
{
P2 = b[i];
for (P2 = b[i]; P2-b[i] < 4; p2++)
{
P3 = &p2;
printf ("%4d", **P3);
}
printf ("\ n");
}
}
Results of output:
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
11 12 13 14
15 16 17 18
19 20 21 22
11 12 13 14
15 16 17 18
19 20 21 22
Four, function pointers and function references
function pointers are one of the biggest advantages of C + +. Advanced programmers are more likely to use references as long as they are using a common pointer, because references are easier to handle. However, when working with functions, the function reference to the contrast function pointer does not necessarily have this advantage. The existing code rarely uses a function reference. The following will show you how to function pointers, how to use function references, and when to use them, respectively.
Examples of ① function pointers
Copy Code code as follows:
#include <iostream>
void print (int i)
{
Std::cout << i << Std::endl;
}
void Multiply (int& ndest, int nby)
{
Ndest *= Nby;
}
void Print_something ()
{
Std::cout << "Something" << Std::endl;
}
int SayHello ()
{
Std::cout << "Hello, world!" << Std::endl;
return 10;
}
int main ()
{
void (*pfunction_1) (int);
pfunction_1 = &print;
Pfunction_1 (1);
Output is 1
void (*pfunction_2) (int&, int) = &multiply;
int i = 1;
Pfunction_2 (i, 10);
Std::cout << "i =" << i << Std::endl;
Output is 10
void (*pfunction_3) ();
Pfunction_3 = &print_something;
Pfunction_3 ();
Output is something
Int (*pfunction_4) ();
Pfunction_4 = &sayHello;
int a = Pfunction_4 ();
The output is Hello, world!
Std::cout << a << std::endl;
Output is 10
return 0;
}
Examples of ② function references
Copy Code code as follows:
#include <iostream>
void print (int i)
{
Std::cout << i << Std::endl;
}
void Print2 (int i)
{
Std::cout << i << Std::endl;
}
void Multiply (int& ndest, int nby)
{
Ndest *= Nby;
}
void Print_something ()
{
Std::cout << "Something" << Std::endl;
}
int SayHello ()
{
Std::cout << "Hello, world!" << Std::endl;
return 10;
}
int main ()
{
void (&rfunction_1) (int);
Error: Reference not initialized! Reference must be initialized
void (&rfunction_2) (int) = print;
Rfunction_2 (1);
Output 1
Rfunction_2 = Print2;
Rfunction_2 (2);
Output 2
void (&rfunction_3) (int&, int) = multiply;
int i = 1;
Rfunction_3 (i, 10);
Std::cout << i << Std::endl;
Output 10
void (&rfunction_4) = print_something;
Rfunction_4 ();
Output something
Int (&rfunction_5) ();
Rfunction_5 = SayHello;
int a = Rfunction_5 (); Output Hello, world!
Std::cout << a << std::endl;
Output 10
return 0;
}
③ function pointers and function references as function arguments
Copy Code code as follows:
#include <iostream>
void print (int i)
{
Std::cout << i << Std::endl;
}
void Print2 (int i)
{
Std::cout << i * 2 << Std::endl;
}
void Printsomething ()
{
Std::cout << "Something" << Std::endl;
}
void SayHello ()
{
Std::cout << "Hello, world!" << Std::endl;
}
void Call_p_func (void (*func) (int))
{
Func (1);
Func (2);
Func (3);
}
void Call_r_func (void (&func) (int))
{
Func (1);
Func (2);
Func (3);
}
void Call_p_function (void (*func) ())
{
Func ();
}
int main ()
{
Std::cout << "function pointers as parameters" << Std::endl;
Call_p_func (&print);
Call_p_func (&print2);
Call_p_function (&printsomething);
Call_p_function (&sayhello);
Call_p_function (SayHello);
The above two sentences are the same for some compilers, but the use of the former is recommended,
This can be a more readable program.
Std::cout << "function reference as parameter" << Std::endl;
Call_r_func (print);
Call_r_func (Print2);
return 0;
}
Summary:
How the declaration of a function pointer is used:
< return type > (* function pointer name) of the function you want to point to < the parameter type of the function you want to point to ...>
To declare a function pointer to the following function:
Copy Code code as follows:
void print (int i)
{
Std::cout << i << Std::endl;
}
Then you can do the following:
void (*pfunction) (int);
Then assign a value to the pfunction with the address of the function:
Pfunction = &print;
Then, pfunction can be used like function print, for example,
Pfunction (1);
Wait a minute.
Declaration and use of function references:
< return type of function to be referenced > (name of & Function Reference) < The type of the function to be referenced ...>=< the name of the function you want to refer to, so that the reference must be initialized at the time of declaration and the reference cannot point to a null value.
To declare a function reference to point to the following function:
Copy Code code as follows:
void print (int i)
{
Std::cout << i << Std::endl;
}
Then you can do the following:
void (&rfunction) (int) =print;
Then, rfunction can be used like function print, for example,
Rfunction (1);
Wait a minute.
Five, const-modified pointers and references
roughly, the const-decorated pointer and reference are divided into three cases, the const-decorated pointer, the const-modifier reference, and the const-decorated pointer reference. The following are discussed separately. The
①const modifier pointer
Const-modifier pointer is divided into three cases, that is, the const modifier pointer itself, the variable (or object) that the const modifier pointer refers to, and the const-decorated pointer itself and the variable (or object) that the pointer refers to.
A. Const modifier pointer itself
in this case, the pointer itself is a constant and cannot be changed, and any modification of the pointer itself is illegal, for example:
double pi = 3.1416;
double* Const PI =π
Double alpha = 3.14;
PI =α //error. Because pointer pi is a constant, it cannot be changed again.
*pi = alpha; //OK. Although the pointer pi cannot be changed, the variable or object that the pointer refers to is variable.
B. The variable (or object) that the const modifier pointer points to
in this case, the pointer itself can change, but the object that the const-decorated pointer points to cannot be changed, for example:
double pi = 3.1416;
Const double* PI =π
Double alpha = 3.14;
*PI = alpha;//error. Because pi points to a constant, *PI cannot be changed.
PI =α//OK. Although the contents of the pointer cannot be changed, the pointer pi itself can be changed. Thus changing *pi in this way.
C. const modifies the pointer itself and the variable (or object) that the pointer points to
in this case, the pointer itself and the variable (or object) to which the pointer is pointing cannot be changed, for example:
double pi = 3.146;
Const double* Const PI =π
//double const* const PI =π
cout << "pi =" << pi << Endl;
cout << "*pi =" << *pi << Endl;
Double alpha = 3.14
*pi = Alpha; Error. Because pi points to a constant, *PI cannot be changed.
//pi =α//error. Because pointer pi is a constant, it cannot be changed again. The
②const modifier reference
Const modifier Reference is not as complex as a pointer-decoration pointer, but only in one form. The reference itself cannot be changed, but the object being pointed to can be changed, see above "first, basic knowledge".
Double pi = 3.1416;
//const double& pi = pi;
Double const& pi = pi; //And the preceding sentence is equivalent
//double& const PI = pi;//has a problem. Many compilers produce warning
cout << PI << Endl;
③const modifier Pointer Reference
We use examples to illustrate.
Double pi = 3.14;
Const double* PPI =π
//const double*& rPI =π//error. Cannot convert double* to const double *&
Const double*& RPI = ppi; //ok. The correct method to declare a pointer reference
Description: Const double*& RPI =π Why is there an error? As we know, references are aliases for referenced objects, and because of this, because RPI is the alias of PPI, the type of RPI and PPI must be exactly the same. From the code snippet above, we can see that the RPI type is a const double*, and the &pi type is double*, so this procedure is wrong.
The following code corresponds to the case in B in ① (that is, the content is not variable and the pointer is variable):
Double pi = 3.1416;
Double API = 3.14;
Const double* PPI =π
Const double* PAPI = &api;
Const double*& RPI = PPI;
Const double*& RAPI = PPI;
*rapi = API; Error. The value that the pointer points to cannot be changed directly
RAPI = PAPI; Ok. The pointer itself can be changed
The use of pointer references there are other situations, which are not mentioned because of the general antiseptic.