C++ review special-pointer topic

pointer

When learning pointers, we must first know that the priority of () is higher than [], and the priority of [] is higher than *

Knowing this, you can quickly understand complex sentences when analyzing sentences that contain pointers.

Member access method

A.B

A is an object or structure, access to member B of A, if A is a pointer, it does not apply
A->B A is a pointer, -> is a member extraction, A->B is to extract a member B in A, and A can only be a pointer to a class or structure
:: Scope operator, A::B represents the name B in scope A, A is the namespace, class, structure
: Represents inheritance
Priority (high to low)
:: Scope resolution
()  
[] Array
-> Member access
++ Suffix increment
--  
! non-
~ Bit not
+ Positive, plus
-  
++ Prefix increment
--  
& address
* Contact reference (pointer)
   
  • Pointer is a variable, which stores address information
    • The value of P is the address
    • The value of *P is the data value pointed to, and *P can be regarded as an ordinary variable
  • Get address value &
    • For ordinary variables, if you want to get the address of the variable, you need to use the address operator & , that is, &a means the address of variable a, which means the same as P
  • The * operator is also known as the dereference operator
  • Declare pointer
    • The declaration of the pointer must specify the data type pointed to, such as int * p;
      • The data type of *p here is int,
      • p is a pointer to int type
    • int *p emphasizes that *p is an int type, and treats *p as an ordinary int type variable
    • int* p emphasizes that int* is a type, that is, p is a pointer to int type, emphasizes int*, and treats int* as a data type
double * p;    //定义声明了一个指向double类型的指针p
double* p;    //定义声明了一个指向double类型的指针p,强调p是指向double类型的指针变量
double *p;    //定义声明了一个指向double类型的指针p,强调*p是double类型
  • Pointer initialization
    • Question: Is the pointer address or the data value pointed to by the pointer initialized?
      • Initialized is the address where the pointer is stored
    • int *p = &a ;
  • Pointers can be compared using relational operators, such as ==, <and >. If p1 and p2 point to two related variables, such as different elements in the same array, then p1 and p2 can be compared.
  • & Operator note
    • When performing an & operation on an array name, you get the address of the entire array, not the address of the first element (array name = address of the first element, without the & operator), although the two addresses are the same, However, there will be obvious differences in operation, as follows:
    • &array[2] and &array get the address value of a 2-byte memory block, and &array is the first address of a 20-byte memory block
  • storage
    • Automatic storage
      • The regular variables defined inside the function use automatic storage space. These variables are also called automatic variables, and the storage space they use becomes the stack.
      • Automatic variables are actually local variables, which are born with function calls and end and die
      • The stack is LIFO last in first out
    • Static storage
      • The storage method that exists during the execution of the program can be defined outside the function body, or by using the keyword static when declaring variables
      • As long as the program is alive, static variables will always exist
    • Dynamic storage
      • The operators new and delete manage a memory pool, which is equivalent to a stack of automatic storage, but here it is called a heap. The stack and the heap are independent of each other.
      • Dynamic storage allocates memory on demand when the program is running, and deletes it when it is used up
  • Template class vector
    • Vector is also a dynamic array, and memory is also managed by new and delete, but vector is automatically completed
    • vector<typeName> name(number); 
    • vector<typeName> name;
  • Pointers and operators
    • Pointer arithmetic has been described above, here is combined with the increment operator
    • *++p, here means that the address value of p is first increased by 1 unit of the number of bytes, and then combined with the * release operator
    • *p++, the same
    • ++*p, here is to treat *p directly as an ordinary variable, combined with the ++ increment operator
    • (*p)++ Here is to regard *p as an ordinary variable

Pointer vs array

Pointer to array

Keep in mind that the following two identities arr are the array name, p is the pointer to the array name address value assignment, p=arr

On the left is the array notation, on the right is the pointer notation

arr[i]  == *(p+i)

&arr[i] == p + i

  • A pointer to the beginning of the array, which can be accessed by using pointer arithmetic operations or array indexing (that is, the above two formulas)
    • Pointers and arrays are not completely interchangeable. The array name is equivalent to a pointer constant , and its value is the first address of the 0th element of the array.
    • The value of the array name cannot be changed, but pointer variables can be operated on
    • The pointer operator * can be applied to the array arr, but it is illegal to modify the value stored in arr, and only the value of the array member of the array represented by var can be modified.
    • Exception: the sizeof operator takes the length of the array name and returns the length of the entire array
    #include <iostream>
    
    using namespace std;
    const int MAX = 3;
    
    int main ()
    {
       int  var[MAX] = {10, 100, 200};
       int  *ptr;
       ptr = var;
        
       for (int i = 0; i < MAX; i++)
       {
          *var = i;    // 这是正确的语法
          var++;       // 这是不正确的
          ptr++;       //TRUE, 指针加1个int单位字节,从而指向了下一个元素
       }
       return 0;
    }
  • The array name is equal to the first address of the 0th element
    • arr is the same as &arr[0]
    • Although arr and &arr have the same value, arr is the first address of the 0th element, and &arr is the first address of the entire array
      • When assigned to a pointer for arithmetic operations, the former will increase or decrease the size of one element memory byte, while the latter will increase or decrease the size of an array byte
  • Create a pointer to an array
    • In the code below:
      • pa is a pointer to the first address of the 0 element of the array
      • pb is a pointer, the same as pa
      • pbb is a pointer, the same value as pa and pb, but pbb points to the entire array
      • pc is a pointer to an array containing 100 doubles
      • pd is an array, the array contains 100 double* pointer elements
double arr[100];
double *pa = arr;
double *pb = &arr[0];
double *pbb = &arr;

double (*pc)[100];
double *pd[100];

new operator allocates memory

  • In C language, the library function malloc() is used to allocate memory, which is also compatible in C++, but it is recommended to use the new operator to allocate memory
  • The operation flow of the new operator:
    • ①In the running phase, it is an int value, that is, int type data. The data has no name, that is, no memory label. Unnamed memory is allocated for this data (this int type data occupies the memory space, but there is no memory for this memory. Space tag)
    • ②Allocate unnamed memory and use pointers to access this memory block
    • ③I just need to tell new, what type of data I need to create
    • ④The new operator will automatically find a suitable memory block and return the address of the memory block
    • ⑤In short, I only need to tell new data type, new will give a corresponding memory block address to a pointer
      • int * ptr = new int;
      • The two data types before and after should correspond, here is int
  • Q: What is the difference between pointer initialization and new allocation of memory?
    • int * p = &a; pointer initialization, data can be accessed through non-pointer variables, that is, the value in the memory block can be modified through a, or it can be modified through *p
    • int * ptr = new int; new allocates memory and can only modify access data through *ptr
  • Q: How much do you know about the address?
    • The address is the name of the memory block, and the variable is the label of the memory block
    • Note: The address is only the name of the first bit of the memory block, such as x01010101, if it is of int type, then adding 32 is the address name of the last bit of the memory block
  • new operator to create a dynamic array
    • When the amount of data is large, you should avoid using conventional arrays, strings, structures, etc., and try to use the new operator to create dynamic arrays
    • Scenario: When you write a program, you find that you are not sure whether to use an array, so whether you need an array or not depends on what data you enter. At this time, you need to understand the problem of static binding and dynamic binding.
      • Static binding: memory is allocated at compile time, regardless of whether the program calls the array or not, it will occupy the corresponding memory space
      • Dynamic binding: No memory is allocated at compile time, that is, a corresponding size of memory space is created at runtime according to whether the program is called or not. The created length is the same as the actual length. This special array is called dynamic array.
    • int *ptr_dynamic_array = new int[11];
      • [] indicates the number of elements
      • new returns the address of the first element of the array
    • When you are done using it, use the delete operator to release the array and directly delete ptr_dynamic_array
    • To use dynamic arrays, you only need to use pointers as array names, such as ptr_dynamic_array[10]
  • Supplement to the new operator
    • Through the new operator, you can create dynamic arrays, or you can create dynamic structures and dynamic classes. The principle is the same as that of new creating dynamic arrays, that is, the memory block is allocated on demand at runtime and the first address of the memory block is returned.
    • inflatable * ps = new inflatable;
      • *ps is a pointer of an inflatable structure type, inflatable* and int* are the same
    • Here to add, if your pointer is a structure, then member access needs to use the member operator -> to access

Pointer arithmetic

  • Pointer +1, here +1 means adding 1 pointer to the number of memory bytes of the type, such as int * p; p+1 means adding 8 bytes to the address value stored in p
  • Array, address, pointer
    short tell[10];
    cout<<tell<<endl;
    cout<<&tell<endl;
    cout<<&tell[0]<<endl;
    • Variable pointers can be incremented , arrays cannot be incremented , and arrays can be regarded as a constant pointer.
    • The array name is the address value of its first element , and the pointer variable stores the address value , so the pointer variable can be used as the array name.
    • To & take the address of the array name, you need to pay attention to:
      • Take the address of the array name, &tell gets the address of the entire array, that is, what you get is the block address of the memory block occupied by an array, &tell
        • After taking the address of the array name, the pointer that &tell can assign points to an array containing 10 elements
        • Put &tell + 2 then, the address must increase by 20
      • Take the address of the first element of the array, &tell[0] is the block address of the memory block occupied by an element, which often defaults to the array name tell
        • Consider the array name tell as a pointer. Since tell is &tell[0] , then tell is a pointer constant pointing to the short type.
        • Add tell+1, then the address is increased by 2 bytes
    • Therefore, for arrays and pointers, either array notation or pointer notation can be used.
int main(){
    double * ptr = new double;
    ptr[1] = 100.21;
    cout<<*(ptr+1)<<endl;
    return 1;
}

// 100.21
#include <iostream>

using namespace std;
const int MAX = 3;

int main ()
{
   int  var[MAX] = {10, 100, 200};
   int  *ptr;

   // 指针中最后一个元素的地址
   ptr = &var[MAX-1];
   for (int i = MAX; i > 0; i--)
   {
      cout << "Address of var[" << i << "] = ";
      cout << ptr << endl;

      cout << "Value of var[" << i << "] = ";
      cout << *ptr << endl;

      // 移动到下一个位置
      ptr--;
   }
   return 0;
}
Address of var[3] = 0xbfdb70f8
Value of var[3] = 200
Address of var[2] = 0xbfdb70f4
Value of var[2] = 100
Address of var[1] = 0xbfdb70f0
Value of var[1] = 10



int *pt = new int [10];
*pt = 5;
pt[0] = 6;
pt[9] = 44;

int coats [10];
* (coats +4) = 99;
//解释:
//coats表示数组第一个元素地址,+4则地址增加4个int内存空间,即移动到coats[4]的位置
//*(coats+4) 和 coats[4] 等价

Discrimination:

short (*pas)[20];
short *pas[20];

int *ar2[4];
int (*ar2)[4];

//解析
//牢记优先级() [] *
short (*pas)[20]; //pas是指针,指向由20个short元素组成的数组的指针

short *pas[20];  //pas是个数组,包含了20个指向short类型指针的数组

int *ar2 [4]; //ar2是个数组,表示由4个int指针组成的数组
//-1-参考int arr[4];表示arr是个int数组,长度为4
//-2-int* ar2[4];表示ar2是个int*数组,长度为4,只不过元素都是只想int的指针

int (*ar2) [4];//ar2是个指针,指向一个包含了4个int的数组

//-1-先看括号里面,(*ar2),表示ar2是个指针
//-2-再看括号外面,int ()[4];表示名为()的int数组,长度为4
  •  

Pointers and const

  • const means constant. For pointers, there are two goals, one is the address value stored by the pointer, and the other is the variable value pointed to by the pointer
  • Directly cite chestnuts
// NO.1 right
int age = 30;
const int * p = &age;  //无法通过p修改age,age自身可修改

// NO.2 right
const int age = 30;
const int * ptr = &age;    //无法通过ptr修改age,age自身不可修改

// NO.3 false
const int age = 30;
int *ptr = &age;     //可通过ptr修改age,age自身不可修改,矛盾,ERROR


  • Next, analyze the following four types, mainly pointer constants, pointer variables, and the relationship between constants and variables
  • Entities of type int cannot be initialized with const int, and vice versa
#include <iostream>

using namespace std;

int main() {
	/*当对象是变量或者常量时,思考const的存在或不同位置,能否导致指针自身和指针指向的对象 改变?*/

	int num = 10;  //当对象是int变量
	int test = 1;
	int * num_ptr0 = &num;					   //  TRUE, *num_ptr0,可修改,num_ptr0可修改,num可修改
	const int * num_ptr1 = &num;			   //  TRUE, *num_ptr1常量不可修改,num_ptr1可修改,num可修改
	int * const num_ptr2 = &num;			   //  TRUE, *num_ptr2可以修改, num_ptr2不可修改,num可修改
	const int* const num_ptr3 = &num;    //   TRUE, *num_ptr3常量不可修改, num_ptr3常量不可修改,num可修改


	const int price = 100; //当对象是int常量
	
	int * price_ptr0 = &price;                     //ERROR, 指针指向类型和指向对象类型不匹配, nt类型的实体不能用const int来初始化,反之可以
	const int *price_ptr1 = &price;             //TRUE, 
	int * const price_ptr2 = &price;			   //ERROR, 指针指向类型和指向对象类型不匹配, int类型的实体不能用const int来初始化,反之可以
	const int* const price_ptr3 = &price;    //TRUE

	return 0;
}
  • When the variable is declared, if there is no exact address to assign, it is a good programming practice to assign a NULL value to the pointer variable. A pointer assigned a NULL value is called a null pointer.
  • To check for a null pointer, you can use the if statement,
#include <iostream>

using namespace std;

int main ()
{
   int  *ptr = NULL;

   cout << "ptr 的值是 " << ptr ;

   return 0;
}

ptr 的值是 0

if(ptr)     /* 如果 ptr 非空,则完成 */
if(!ptr)    /* 如果 ptr 为空,则完成 */

Function pointer

Pointer to function

  • Get the address of the function
    • Use the function name directly (note the distinction between the function name and the function return value), as follows, think is the function name, and think() is the function return value.
process(think);
process(think());
  • Declare function pointers and initialize assignments
    • Keep in mind the priority () [] * The order is from high to low
    • Need to specify the return type and signature of the function (directly replace the function name declared by the function with a pointer, as follows)
double pam(int);
double (*f)(int);

f = pam;
  • Function pointer call
    • You can directly use (*f) or f as the function name pam, both are fine, pay attention to the parentheses () of (*f)
double pam(int);
double (*f)(int);
f = pam;

double x = pam(4);
double y = (*f)(4);
double z = f(4);
  • Discrimination
double pam(int);
double *f1(int);
double (*f2)(int);


int arr[10];
int *p = &arr[0];
int *a = arr;
int *b = &arr;
int *c[10] = &arr;
int (*d)[10] = &arr;


In the above code:

f1 is a function, the return value type is a double* pointer

f2 is a pointer, pointing to a function, the type is double (*)(int);

p is a pointer to the first address of element 0 of the array arr

a is a pointer, the same as p (array name arr is the first address of element 0)

b is a pointer. Although it has the same value as a, it points to the first address of the entire array memory block. When b performs +1 operation, it will increase the number of bytes of the entire array memory.

c is an array, an array containing 10 int* pointer elements

d is a pointer that points to an array containing 10 int elements

In-depth study of function pointers

Function prototype

In the function prototype, the signature or parameter list has the following rules:

  • arr[] is equivalent to *arr
  • The identifier const double ar[] can be omitted and simplified to const double [], const double *arr is the same as const double *
    • It cannot be omitted in function definition!

Array containing function pointers

const double * (*pa[3])(const double *,int) = {f1,f2,f3};

Statement writing idea: first write the return type and signature const double * ()(const double*, int) and then fill in an array expression containing pointer *pa[3] in ()

 

Pointer to an array containing function pointers

const double * (*(*pa)[3])(const double *, int) = &pa;

Statement writing idea: first write the return type and signature const double * ()(const double *, int), and then add a pointer expression to the array containing pointer elements *(*pa)[3]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/Mrsherlock_/article/details/109167479