指针
基本使用
指针是用于存储变量地址的特殊变量。通过指针,可以间接访问或修改变量的值。
1 2 3
| int num = 10; int* p = # *p = 20;
|
在上述代码中,num
的地址被存入指针 p
中,并通过 *p
进行解引用,间接给 num
赋值。
指针与数组
数组名在大多数情况下会被解释为指向其第一个元素的指针。由于数组元素在内存中是连续的,因此可以通过指针遍历数组。
1 2 3 4 5
| int arr[5] = {1, 2, 3, 4, 5}; int* p = arr; for (int i = 0; i < 5; ++i) { cout << *(p + i) << " "; }
|
你可以定义一个指针数组用来存储多个指针,或者声明一个数组指针来指向一个数组。
1 2 3 4 5 6 7
| int arr[5] = {1, 2, 3, 4, 5};
int *p1[5] = {&arr[0], &arr[1], &arr[2], &arr[3], &arr[4]};
int (*p2)[] = &arr;
|
优先级:() > [] > *
对于 int *p1[5]
,[]
的优先级高,p1
首先被解析为数组,数组中的元素类型为整型指针。
对于 int (*p2)[]
,使用 ()
提升优先级,强制将 p2
解析为指针。
多级指针
多级指针是指向指针的指针,通过它我们可以间接访问多级嵌套的变量值。
1 2 3 4
| int num = 10; int* p1 = # int** p2 = &p1; cout << **p2 << endl;
|
指针与运算符
指针与运算符经常用来组合出阴间题目,需要多加注意。
1 2 3 4 5 6
| char s1[20]="123apple",*p=s1, **pp=&p; cout << *pp + 3 << endl; cout << *p++ << endl; cout << *++p << endl; cout << *pp << endl; cout << **pp << endl;
|
这段代码中:
*pp + 3
等价于 p + 3
*p++
和 *++p
分别等价于 *(p++)
和 *(++p)
*pp
等价于 p
,此时 p
指向 &s1[2]
,故连续输出后面的字符串
**pp
等价于 *p
,故输出 s1[2]
,即为 3
动态内存分配
在 C++ 中,可以使用 new
和 delete
运算符进行动态内存分配和释放。
1 2 3 4 5 6 7
| int* p = new int(10); delete p;
int n; cin >> n; int* arr = new int[n]; delete[] arr;
|
使用完动态分配的变量后一定记得调用 delete
或 delete[]
释放内存,否则会导致内存泄漏。
多级指针在动态分配二维数组时非常有用,因为二维数组本质上可以看作是指针的数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| int rows, cols; cin >> rows >> cols;
int** arr = new int*[rows];
for (int i = 0; i < rows; ++i) { arr[i] = new int[cols]; }
for (int i = 0; i < rows; ++i) { delete[] arr[i]; } delete[] arr;
|
如果你不想使用多级指针,也可以使用上文提到的数组指针。
这种方式不太常见,并且写法有点反直觉。
1 2 3 4 5 6 7 8
| int rows, cols; cin >> rows >> cols;
int (*arr)[cols] = new int[rows][cols];
delete[] arr;
|
常量指针与指针常量
常量指针 const int* p
或 int const *p
:指针指向的值不可修改,但指针本身可以指向其他地址。
指针常量 int* const p
:指针本身不可修改,但指向的值可以修改。
指向常量的指针常量 const int* const p
:指针本身和指向的值都不可修改。
函数指针
函数指针用于指向函数,可以通过它调用函数。
1 2 3 4 5 6
| int add(int x, int y) { return x + y; }
int (*p)(int, int) = add;
|
函数指针常用于自定义排序条件,以下是一个冒泡排序示例,它通过传入函数指针来实现排序的灵活性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| #include <iostream> using namespace std;
bool descending(int a, int b) { return a > b; }
bool ascending(int a, int b) { return a < b; }
void bubbleSort(int arr[], int size, bool (*compare)(int, int)) { for (int i = 0; i < size - 1; ++i) { for (int j = 0; j < size - i - 1; ++j) { if (!compare(arr[j], arr[j + 1])) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } }
int main() { int arr[] = {4, 2, 3, 5, 1}; int size = sizeof(arr) / sizeof(int);
bubbleSort(arr, size, ascending); for (int i = 0; i < size; ++i) { cout << arr[i] << " "; } cout << endl;
bubbleSort(arr, size, descending); for (int i = 0; i < size; ++i) { cout << arr[i] << " "; } cout << endl;
return 0; }
|
指针与结构体
指针常用于操作结构体,特别是在动态内存分配时。
1 2 3 4 5 6 7 8
| struct Person { string name; int age; }; Person* p = new Person; p->name = "Alice"; p->age = 30; delete p;
|