C++ 指针
在 C++ 中,指针(pointer)是存放“内存地址”的变量,通过指针可以间接地访问或修改内存中的数据。下面分几个层面来介绍指针的概念与用法。
1. 基本概念
- 什么是指针
指针本质上是一个整型变量,它的值是另一个变量在内存中的地址。 - 声明与初始化
int x = 10; // 普通整型变量 int* p = &x; // 声明一个指向 int 的指针 p,并初始化为 x 的地址
int* p
:指向int
的指针&x
:取变量x
的地址*p
:解引用(dereference),即通过指针访问或修改它所指的对象
2. 指针的基本操作
#include <iostream>
using namespace std;
int main() {
int x = 10;
int* p = &x; // p 存放 x 的地址
cout << "x = " << x << "\n";
cout << "&x = " << &x << "\n";
cout << "p = " << p << "\n";
cout << "*p = " << *p << "\n"; // 解引用,输出 10
*p = 20; // 通过指针修改 x
cout << "修改后 x = " << x << "\n";
}
p = &x;
:将指针p
指向变量x
*p
:读取或写入p
指向的内存
3. 指针与数组
在 C++ 中,数组名在多数表达式中会退化(decay)为指向首元素的指针。
int a[5] = {1,2,3,4,5};
int* p = a; // 等价于 &a[0]
for (int i = 0; i < 5; ++i) {
cout << *(p + i) << " "; // 指针算术:依次访问 a[0]…a[4]
}
- 指针算术:
p + i
会移动i * sizeof(int)
字节 - 访问数组元素:
p[i]
与*(p + i)
等价
4. 空指针与野指针
- 空指针:不指向任何有效对象
int* p = nullptr; if (p) { // 不会进入,因为 p 为 nullptr }
- 野指针:未初始化或已释放指向无效内存,使用会导致未定义行为。
int* p; // 未初始化,值未知(野指针)
5. 指向指针的指针
可以通过多重指针访问多层地址:
int x = 42;
int* p = &x; // 指向 int
int** pp = &p; // 指向指针 p
cout << **pp << "\n"; // 先解一次 pp 得到 p,再解一次得到 x
6. 函数指针
- 声明与调用
int add(int a, int b) { return a + b; } // 声明一个指向函数(int,int)->int 的指针 int (*func)(int, int) = &add; cout << func(2,3) << "\n"; // 输出 5
- 用途:回调函数、策略模式等。
7. 动态内存与智能指针
7.1 原始指针与 new/delete
int* p = new int(100); // 在堆上分配一个 int,初始化为 100
// ...
delete p; // 释放内存
p = nullptr;
- 注意:每个
new
必须对应一个delete
,否则会内存泄漏。
7.2 C++11 智能指针(推荐)
std::unique_ptr<T>
:独占所有权std::shared_ptr<T>
:引用计数,多个共享所有权std::weak_ptr<T>
:配合shared_ptr
,解决循环引用
#include <memory>
auto up = std::make_unique<int>(200); // unique_ptr<int>
auto sp = std::make_shared<int>(300); // shared_ptr<int>
cout << *up << ", " << *sp << "\n"; // 输出 200, 300
// 自动释放,无需 delete
智能指针帮助管理资源、避免内存泄漏和悬空指针。
8. 常量指针与指针常量
- 指针常量(pointer constant):指针本身不可修改
int x = 1, y = 2; int* const p = &x; // p 是常量,必须初始化,之后不可再指向其他地址 *p = 5; // 合法:修改 p 指向的值 // p = &y; // 错误:不能修改指针本身
- 常量指针(pointer to constant):指向的值不可修改
const int* p = &x; // p 可变,但 *p 不可修改 // *p = 10; // 错误:不能通过 p 修改 x p = &y; // 合法:可以指向其他地址
- 常量指针常量
const int* const p = &x; // 既不能修改 *p,也不能修改 p
9. 注意事项与最佳实践
- 尽量使用智能指针(
unique_ptr
/shared_ptr
)管理动态内存,避免手动new
/delete
。 - 检查空指针(
nullptr
)后再解引用,避免崩溃。 - 避免过度指针算术,出错率高且可读性差,推荐使用标准容器(如
std::vector
)和迭代器。 - 函数参数传递:若要修改指针本身,可用指向指针的指针;否则优先使用引用或智能指针。
通过掌握以上各类指针用法,你就能在 C++ 中高效、安全地进行底层内存操作与资源管理。