- C++
在C++里,指针是一种极为关键的变量类型,它的作用是存储内存地址
- 2025-7-19 15:18:17 @
在C++里,指针是一种极为关键的变量类型,它的作用是存储内存地址。接下来,我会通过一系列简单易懂的示例,带你深入了解指针的基本概念、实际用途以及相关注意事项。
一、指针的基本概念
指针本质上也是一种变量,但它存储的不是普通的数据,而是内存地址。通过这个内存地址,就能访问存储在该地址上的数据。
下面是指针的基本声明和初始化方式:
int num = 42; // 定义一个整型变量num,值为42
int* ptr = # // 定义一个指向整型的指针ptr,并将其初始化为num的地址
这里需要留意几个关键符号:
*
:在声明时,它表明这是一个指针变量;在使用时,它的作用是解引用,也就是获取指针所指向的值。&
:取地址运算符,用于获取变量的内存地址。
二、指针的基本操作
下面为你展示指针的常见操作示例:
#include <iostream>
using namespace std;
int main() {
int num = 42;
// 1. 声明指针并初始化
int* ptr = #
// 2. 输出变量的值和地址
cout << "变量num的值: " << num << endl; // 输出: 42
cout << "变量num的地址: " << &num << endl; // 输出: 0x7ffe...(实际地址)
// 3. 输出指针的值和指针所指向的值
cout << "指针ptr存储的地址: " << ptr << endl; // 输出: 0x7ffe...(与num的地址相同)
cout << "指针ptr指向的值: " << *ptr << endl; // 输出: 42
// 4. 修改通过指针修改变量的值
*ptr = 100;
cout << "修改后变量num的值: " << num << endl; // 输出: 100
// 5. 空指针
int* nullPtr = nullptr; // C++11引入的空指针常量
cout << "空指针的值: " << nullPtr << endl; // 输出: 0
return 0;
}
三、指针与数组
在C++中,数组名在很多时候会被隐式转换为指向数组首个元素的指针,下面来举例说明:
#include <iostream>
using namespace std;
int main() {
int arr[5] = {10, 20, 30, 40, 50};
// 1. 数组名作为指针
int* ptr = arr; // 等价于 int* ptr = &arr[0];
// 2. 使用指针访问数组元素
cout << "通过指针访问数组元素:" << endl;
cout << "*ptr = " << *ptr << endl; // 输出: 10
cout << "*(ptr+1) = " << *(ptr+1) << endl; // 输出: 20(指针偏移1个单位)
// 3. 使用指针遍历数组
cout << "遍历数组:" << endl;
for (int i = 0; i < 5; i++) {
cout << "arr[" << i << "] = " << *(ptr+i) << endl;
}
// 4. 指针算术运算
ptr++; // 指针向后移动一个单位(移动sizeof(int)字节)
cout << "ptr++后指向的值: " << *ptr << endl; // 输出: 20
return 0;
}
四、动态内存分配
在C++中,可以利用new
和delete
操作符来进行动态内存分配和释放,具体用法如下:
#include <iostream>
using namespace std;
int main() {
// 1. 动态分配单个变量
int* ptr1 = new int; // 分配一个整型大小的内存
*ptr1 = 100;
cout << "*ptr1 = " << *ptr1 << endl; // 输出: 100
// 2. 动态分配数组
int* arr = new int[5]; // 分配包含5个整型的数组
for (int i = 0; i < 5; i++) {
arr[i] = i * 10;
}
cout << "动态数组内容:" << endl;
for (int i = 0; i < 5; i++) {
cout << arr[i] << " ";
}
cout << endl;
// 3. 释放内存
delete ptr1; // 释放单个变量的内存
delete[] arr; // 释放数组的内存
// 4. 野指针问题(释放后未置空)
ptr1 = nullptr; // 推荐释放后将指针置空,避免野指针
return 0;
}
五、指针与函数
指针在函数参数传递和返回值方面都有重要应用,下面是具体示例:
#include <iostream>
using namespace std;
// 1. 传递指针作为参数(修改实参的值)
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 2. 返回指针(谨慎使用!)
int* createArray(int size) {
int* arr = new int[size];
for (int i = 0; i < size; i++) {
arr[i] = i;
}
return arr; // 返回动态分配的数组指针
}
int main() {
// 1. 测试指针参数
int x = 10, y = 20;
cout << "交换前: x=" << x << ", y=" << y << endl;
swap(&x, &y);
cout << "交换后: x=" << x << ", y=" << y << endl;
// 2. 测试返回指针
int* arr = createArray(5);
cout << "动态创建的数组:" << endl;
for (int i = 0; i < 5; i++) {
cout << arr[i] << " ";
}
cout << endl;
// 释放内存,防止内存泄漏
delete[] arr;
return 0;
}
六、指针的注意事项
在使用指针时,有几个重要的注意事项需要你牢记:
- 空指针检查:在解引用指针之前,一定要先确认指针不为
nullptr
,防止程序崩溃。 - 内存泄漏:通过
new
动态分配的内存,在使用完毕后必须使用delete
进行释放,避免内存泄漏。 - 野指针:释放内存后,要记得将指针置为
nullptr
,防止误操作野指针。 - 数组越界:使用指针访问数组时,要确保访问范围在数组的有效边界内。
- 深拷贝与浅拷贝:当指针作为类成员时,要特别注意拷贝构造函数和赋值运算符的正确实现。
七、常见错误示例
下面为你列举一些使用指针时常见的错误:
// 错误1:未初始化指针(野指针)
int* ptr;
*ptr = 10; // 危险!ptr指向随机内存地址
// 错误2:释放内存后使用指针
int* ptr = new int;
delete ptr;
*ptr = 20; // 错误!ptr已成为野指针
// 错误3:重复释放内存
int* ptr = new int;
delete ptr;
delete ptr; // 错误!重复释放同一块内存
// 错误4:返回局部变量的指针
int* getNumber() {
int num = 42;
return # // 错误!num是局部变量,函数返回后内存已释放
}
只要你掌握了上述内容,就能在C++编程中安全且高效地使用指针啦!指针虽然功能强大,但也需要谨慎使用,避免出现各种潜在的问题。
7 条评论
-
admin SU @ 2025-7-20 14:30:25
#include <iostream> using namespace std; int main() { // 1. 动态分配单个变量 //int* ptr1 = new int; // 分配一个整型大小的内存 相当于 int* ptr1 = (int*)malloc(sizeof(int)); //上面代码相当于创建了一个int类型的变量 //C++ new叫做动态内存分配,new是一个运算符 new构造、构建、申请、分配 //*ptr1 = 100; int* ptr1 = new int(200);// 分配一个整型大小的内存,并初始化为200 cout << *ptr1 << endl;// 输出200 return 0; // 返回0表示程序正常结束 }
-
2025-7-20 14:19:18@
#include <iostream> using namespace std; int main() { int arr[5] = { 10, 20, 30, 40, 50 }; // 1. 数组名作为指针 int* ptr = arr; // 等价于 int* ptr = &arr[0]; //指针也就是地址,一般情况是按照字节编址的 一个字节一个地址 for (int i = 0; i < 5;i++) { cout << "arr[" << i << "] = " << arr[i] << endl;// 使用数组名访问数组元素 下标访问符 } cout << endl;// 换行 for (int i = 0; i < 5; i++) { cout << "ptr[" << i << "] = " << *(ptr + i) << endl; // 使用指针访问数组元素 } cout << endl;// 换行 return 0; // 返回0表示程序正常结束 }
-
2025-7-20 14:14:43@
#include <iostream> using namespace std; int main() { int arr[5] = { 10, 20, 30, 40, 50 }; // 1. 数组名作为指针 int* ptr = arr; // 等价于 int* ptr = &arr[0]; //指针也就是地址,一般情况是按照字节编址的 一个字节一个地址 //int* int类型的指针,指向int类型的变量,基于int类型的指针+1,加四个字节 //一个int类型的变量占用4个字节,所以指针+1会跳过4个字节 cout << arr << endl; // 输出数组的首地址 cout << arr + 1 << endl; // 输出数组第二个元素的地址 cout << arr + 2 << endl; // 输出数组第三个元素的地址 cout << *(arr + 2) << " " <<arr[2]<< endl; // 输出数组第三个元素的地址 []叫做下标运算符,等价于*(arr + 2),即访问数组第三个元素的值 return 0; // 返回0表示程序正常结束 }
-
2025-7-20 14:01:32@
-
2025-7-20 13:53:31@
-
2025-7-20 13:51:45@
#include <iostream> using namespace std; int main() { int a = 100; int* p = &a; // 定义一个指针p,指向变量a的地址 &a 是取地址运算符 *是指针运算符 cout << "a的值: " << *p << endl; // 输出指针p所指向的变量a的值 *是解引用运算符 int& b = a; // 定义一个引用变量b,引用变量a &是引用运算符 cout << "a的值: " << b << endl; // 输出变量a的值 return 0; // 返回0表示程序正常结束 }
-
2025-7-20 13:47:54@
#include <iostream> using namespace std; int main() { int num = 42; // 定义一个整型变量num,值为42 int* ptr = # // 定义一个指向整型的指针ptr,并将其初始化为num的地址 //int* 基于int的指针类型 cout << ptr << endl;// 输出指针ptr的值,即num的地址 cout << &num << endl; // 输出num的地址 &取地址运算符 不是引用符号 cout << *ptr << endl; // 输出指针ptr所指向的值,即num的值 //*ptr 解引用运算符,获取指针ptr所指向的值 间接访问num的值42 cout << num << endl; // 直接输出num的值 // 通过指针修改num的值 *ptr = 100; // 将ptr所指向的值修改为100 cout << num << endl; // 再次输出num的值,应该是100 return 0; // 返回0表示程序正常结束 }
- 1