目录
什么是指针
指针变量的定义
指针变量定义语法
注意
指针所占内存空间
空指针
野指针
函数指针
声明函数指针
初始化函数指针
使用函数指针调用函数
指针的使用
const修饰指针
const修饰指针 --- 指针常量(constant pointer)
const修饰常量 --- 常量指针(pointer to const)
const即修饰指针,又修饰常量(constant pointer to const)
指针和数组
指针和函数
指针作为函数参数
返回指针的函数
函数指针
动态内存分配
什么是指针
C++中的指针是一种变量,它存储了一个内存地址。通过指针,我们可以访问和修改这个内存地址中的数据。
内存编号是从0开始记录的,一般用十六进制数字表示
可以利用指针变量保存地址,也可以通过指针间接访问内存
指针变量的定义
指针变量定义语法
数据类型 * 变量名;
int num = 10; // 声明一个整数变量
int* ptr;
ptr = &num ; // 将num的地址赋值给指针ptr
int num = 10; // 声明一个整数变量
int* ptr = # // 将num的地址赋值给指针ptr
注意
普通变量存放的是数据,指针变量存放的是地址,利用指针可以记录地址
指针的声明需要指定所指向的数据类型,可以使用 "*" 符号进行声明。
" * "靠近数据类型或者靠近变量名都行,意义一样。 int* a; 相当于 int *a;
我们可以通过 & 操作符(取地址符)获取变量的地址
指针变量可以通过" * "操作符,操作指针变量指向的内存空间,这个过程称为解引用
对指针变量解引用,可以操作指针指向的内存及所指内存的数据
指针所占内存空间
在32位系统中,指针通常占用4个字节(32位),而在64位系统中,指针通常占用8个字节(64位)。需要注意的是,由于不同系统和编译器的差异,指针的大小可能会有一些变化,但是通常情况下遵循上述的规律。指针的大小和指针所指向的类型无关。不论指针指向的是一个整数、字符、对象还是其他数据类型,指针本身的大小是相同的。
空指针
空指针(Null Pointer)是指向内存中编号为0的空间的指针。可以使用字面值常量nullptr
或关键字NULL
来表示空指针。常用于初始化指针变量。
int* ptr = NULL; // 使用NULL初始化指针// int* ptr = nullptr; // 使用nullptr初始化指针
空指针可以作为合法的指针值存在,是一个特殊的指针值,表示指针不引用任何对象或函数。对空指针进行解引用或访问其指向的内容会导致未定义的行为。
野指针
野指针(Wild Pointer)是指向非法的内存空间的指针变量,指向的内存地址是未知、无效或未初始化的。野指针的出现通常是由于指针变量没有被正确初始化或者在释放了指针所指向的内存后仍然保留了指向已释放内存的指针。对野指针进行解引用或访问其指向的内容同样会导致未定义的行为。为了避免野指针的出现,我们应该始终确保指针在使用之前被正确初始化,且在不再需要时及时对指针进行释放或重置。
int * p = (int *)0x1100;//指针变量p指向内存地址编号为0x1100的空间
cout << *p << endl;//访问野指针报错
函数指针
函数指针是指向函数的指针变量。它可以存储函数的地址,并且可以通过该指针来间接调用函数。函数指针允许我们以更灵活的方式使用函数,可以将函数作为参数传递给其他函数,或者将函数指针作为结构体的成员进行操作。
声明函数指针
使用
(*指针变量名)
来声明一个函数指针变量,括号中是指针变量的名称。
int (*funcPtr)(int, int); // 声明一个函数指针变量
初始化函数指针
将函数指针指向一个具体的函数,可以直接将函数的名称赋值给函数指针。
funcPtr = add; // 将函数指针指向 add 函数
使用函数指针调用函数
通过函数指针来间接调用相应的函数。
int result = funcPtr(5, 3); // 使用函数指针调用函数
指针的使用
const修饰指针
总结:指针常量,即指针是常量;常量指针,即常量的指针。
const修饰指针 --- 指针常量(constant pointer)
指针本身是一个常量,不能修改指针的值,但可以通过指针访问和修改指向的变量。
int x = 5;
int* const ptr = &x; // ptr 是一个指向整数的常量指针
*ptr = 10; // 可以通过 ptr 修改所指向的变量的值,即 x 的值被修改为 10
// ptr = nullptr; // 错误,不能修改指针的值
const修饰常量 --- 常量指针(pointer to const)
指针指向的对象是一个常量,不能通过指针修改对象的值。
int x = 5;
const int* ptr = &x; // ptr 是一个指向常量整数的指针
// *ptr = 10; // 错误,不能通过 ptr 修改所指向的常量的值
x = 10; // 可以直接修改变量的值
ptr = nullptr; // 可以修改指针的值
const即修饰指针,又修饰常量(constant pointer to const)
既不能修改指针的值,也不能通过指针修改所指向的常量的值。
const int* const ptr = &x; // ptr 是一个指向常量整数的常量指针
// *ptr = 10; // 错误,不能通过 ptr 修改所指向的常量的值
// ptr = nullptr; // 错误,不能修改指针的值
指针和数组
数组名本身就是一个指向数组首元素的指针,可以通过指针遍历数组元素。
例如
int arr[] = {1, 2, 3}; int* ptr = arr;
将数组名 arr
的地址赋给指针 ptr
,然后可以通过操作指针来访问数组元素。
例如
*ptr
是第一个元素,*(ptr + 1)
是第二个元素
(可以把指针当数组用,也能把数组当指针用)
指针和函数
利用指针作函数参数,可以修改实参的值,如果不想修改实参,就用值传递,如果想修改实参,就用地址传递。
指针作为函数参数
可以将指针作为函数的参数,通过指针传递数据或者修改指针指向的数据。这样可以避免在函数中进行大量的数据复制,提高程序的效率。
void updateValue(int* ptr) {*ptr = 10; // 修改指针指向的数据
}
int main() {int x = 5;updateValue(&x); // 将 x 的地址传递给函数// 现在 x 的值变为 10return 0;
}
返回指针的函数
函数可以返回指针类型的值,这样可以返回动态分配的内存地址或者现有变量的地址等。但需要注意在返回指针之前,确保指针指向的数据仍然有效。
int* createArray() {int* arr = new int[5]; // 动态分配一个 int 数组for (int i = 0; i < 5; ++i) {arr[i] = i+1;}return arr; // 返回数组的首地址
}
int main() {int* ptr = createArray(); // 接收返回的指针// 使用指针访问数组的元素for (int i = 0; i < 5; ++i) {cout << ptr[i] << " "; // 输出: 1 2 3 4 5}delete[] ptr; // 释放动态分配的内存return 0;
}
函数指针
见上文
动态内存分配
使用 new
关键字可以在堆上动态分配内存,并返回一个指向分配内存的指针。
int* ptr = new int;//动态分配了一个整数大小的内存,并将其地址赋给指针 ptr。delete ptr;//使用完毕后,需要使用 delete 关键字释放动态分配的内存