C++_指针01_指针及其关键点
指针是C++的“双刃剑”:掌握它,你将能写出高效、灵活的代码;滥用它,则可能导致难以调试的错误。在现代C++中,应尽量使用RAII和智能指针来管理资源,将指针的使用限制在必要场景。
·
在C++中,指针(Pointer) 是一个非常核心且强大的概念,它直接操作内存地址,是实现动态内存管理、高效数据结构(如链表、树)、函数参数传递优化等的关键工具。然而,指针也因其复杂性和易错性而“臭名昭著”。下面系统地介绍C++中指针及其关键点。
一、指针的基本概念
指针是一个变量,其值为另一个变量的内存地址。通过指针,你可以间接访问和操作该地址上的数据。
基本语法:
数据类型 *指针名;
示例:
int a = 10;
int *p = &a; // p 是指向整型变量 a 的指针,&a 是 a 的地址
cout << "a 的值: " << a << endl; // 输出: 10
cout << "a 的地址: " << &a << endl; // 输出: 0x7fff... (内存地址)
cout << "p 的值: " << p << endl; // 输出: 0x7fff... (同上)
cout << "*p 的值: " << *p << endl; // 输出: 10 (*p 是解引用,访问 p 指向的内容)
二、指针的关键点(核心概念与注意事项)
1. 取地址运算符 &
用于获取变量的内存地址。
例如:int *p = &a; 中的 &a。
2. 解引用运算符 *
用于访问指针所指向的内存地址中的值。
例如:*p = 20; 会将 a 的值修改为 20。
空指针或野指针解引用会导致未定义行为(通常程序崩溃)。
3. 指针的初始化与赋值
必须初始化:未初始化的指针是“野指针”,指向随机内存,解引用极其危险。
int *p; // 危险!p 是野指针
int *q = nullptr; // 推荐:初始化为 nullptr
int *r = &a; // 推荐:指向一个有效变量
4. 空指针 nullptr(C++11)
用于表示指针不指向任何对象。
替代旧的 NULL(通常是 0 或 ((void*)0))和直接使用 0。
int *p = nullptr;
if (p) { /* 检查指针是否有效 */ }
5. 指针与数组的关系
数组名本质上是一个指向首元素的指针。
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr; // 等价于 &arr[0]
cout << *p << endl; // 输出: 1
cout << *(p+1) << endl; // 输出: 2
指针算术:p + 1 指向下一个元素(地址增加 sizeof(类型) 字节)。
6. 指针与函数
函数参数传递:通过指针可以修改实参的值(类似引用,但更灵活)。
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int x = 1, y = 2;
swap(&x, &y); // x 和 y 的值被交换
函数返回指针:需谨慎,避免返回局部变量的地址(局部变量在函数结束时销毁)。
int* func() {
int local = 10;
return &local; // 错误!返回局部变量地址,悬空指针
}
7. 动态内存管理(new 和 delete)
使用 new 在堆上分配内存,返回指向该内存的指针。
使用 delete 释放内存,防止内存泄漏。
int *p = new int(42); // 分配一个 int,初始化为 42
cout << *p << endl; // 输出: 42
delete p; // 释放内存
p = nullptr; // 避免悬空指针
int *arr = new int[10]; // 分配数组
delete[] arr; // 释放数组,注意使用 delete[]
8. 悬空指针(Dangling Pointer)
指向已被释放或销毁的内存的指针。
使用悬空指针是未定义行为。
解决方法:释放内存后立即将指针置为 nullptr。
9. 常量指针与指向常量的指针
指向常量的指针:不能通过指针修改值。
深色版本
const int *p = &a; // 或 int const *p
// *p = 20; // 错误!不能修改
p = &b; // 可以改变指针指向
常量指针:指针本身不能改变指向。
int *const p = &a;
*p = 20; // 可以修改 a 的值
// p = &b; // 错误!不能改变 p 的指向
指向常量的常量指针:
const int *const p = &a;
// *p = 20; // 错误
// p = &b; // 错误
10. 多级指针(指针的指针)
指向指针的指针。
深色版本
int a = 10;
int *p = &a;
int **pp = &p; // pp 指向 p
cout << **pp << endl; // 输出: 10
三、指针的常见错误与陷阱
四、现代C++中的指针使用建议
虽然指针功能强大,但现代C++更推荐使用更安全的替代方案:
优先使用引用(&):当不需要重新绑定且不为 nullptr 时。
使用智能指针(C++11):
std::unique_ptr<T>:独占所有权,自动释放。
std::shared_ptr<T>:共享所有权,引用计数。
std::weak_ptr<T>:解决循环引用。
#include <memory>
auto p = std::make_unique<int>(42);
// 无需手动 delete,离开作用域自动释放
使用容器:如 std::vector、std::array 替代原始数组。
使用 std::string:替代字符指针。
总结
指针是C++的“双刃剑”:掌握它,你将能写出高效、灵活的代码;滥用它,则可能导致难以调试的错误。在现代C++中,应尽量使用RAII和智能指针来管理资源,将指针的使用限制在必要场景。
更多推荐
所有评论(0)