指针保存对象的地址,通过解引用读写所指内存。C++ 仍保留指针,但日常代码更常组合使用引用、std::vector 与智能指针,以减少裸指针带来的空指针与悬垂风险。本节说明何时仍需要指针、nullptr 与 const 限定,并衔接引用与智能指针;已学过C 语言指针的读者可重点看 C++ 差异列。
指针、引用与容器:怎么选
| 手段 | 典型用途 | 注意 |
|---|---|---|
std::vector 等容器 | 元素个数变化、需要迭代与算法 | 优先于手动 new[] |
引用 T& | 函数参数、运算符重载、别名 | 必须绑定有效对象,不可空 |
指针 T* | 可选对象、C API、链表节点、重绑定 | 判空、生命周期、优先智能指针管理堆内存 |
取地址与解引用
普通变量保存值;指针保存地址。对指针解引用(*)按该地址访问对象;声明里的 * 表示类型为指针,与表达式中的解引用含义不同。
基本规则
&取地址:&value得到value的地址,类型为int*,可赋给同类型指针。*解引用:在表达式中对指针使用*ptr访问所指对象;声明中的*表示该标识符是指针类型,含义不同。- 初始化:指针声明后应绑定有效地址或
nullptr;未初始化的指针解引用属于未定义行为。
声明与基本操作
#include <iostream>
int main() {
int value = 42;
int* ptr = &value;
std::cout << "解引用: " << *ptr << "\n";
*ptr = 100;
std::cout << "修改后 value: " << value << "\n";
return 0;
}典型输出:
解引用: 42
修改后 value: 100写法 int* ptr 与 int *ptr 等价,* 属于声明符的一部分;习惯上常将 * 靠近类型或靠近名字,但同一声明中只应对指针标识符使用一个 *。
通过指针修改所指对象
int a = 1;
int* p = &a;
a += 1;
*p += 1;
std::cout << a << "\n"; // 3*p 与直接写 a 修改同一对象。向函数传递指针形参以便修改调用方变量时,需保证指针有效且类型匹配,参见函数与引用形参的对比。
空指针 nullptr
int* p = nullptr;
if (p != nullptr) {
std::cout << *p;
}C++11 起推荐使用关键字 nullptr,类型为 std::nullptr_t,可隐式转换为任意指针类型,比宏 NULL 更安全。解引用空指针属于未定义行为;使用前须判空。
指针与数组
数组名在多数表达式中会转换为指向首元素的指针;下标访问与指针算术对应:
int a[] = {1, 2, 3};
int* p = a; // 等价于 &a[0]
std::cout << *(p + 1) << "\n"; // 2
std::cout << p[2] << "\n"; // 3p + 1 指向下一个 int,步长为 sizeof(int)。越界指针算术与解引用同样危险。容器场景优先使用 std::vector 与范围 for,见vector。
const 与指针
下列两种写法含义不同,宜对照记忆:
| 声明形式 | 含义 |
|---|---|
const int* p 或 int const* p | 不能通过 p 修改所指 int,可改 p 的指向 |
int* const p | p 本身不可改指向,可通过 p 修改 int |
const int* const p | 所指对象与指针指向均不可通过 p 改变 |
只读字符串字面量常用 const char*;C++ 中更推荐使用 std::string,见std::string。
指针的大小
#include <iostream>
int main() {
int* pi = nullptr;
double* pd = nullptr;
std::cout << sizeof(pi) << " " << sizeof(pd) << "\n";
return 0;
}同一平台上各类指针所占字节数通常相同,因其保存的都是地址宽度,与所指类型无关。
几类需区分的指针
- 空指针:不指向有效对象;使用前应判
nullptr。 - 未初始化指针:指向不确定地址,解引用未定义;应赋有效地址或
nullptr。 - 悬垂指针:所指对象已销毁仍继续使用;delete 后宜将指针置空,并优先用智能指针管理生命周期。
- 函数指针:保存函数地址,用于回调或算法;与成员函数指针不同,属进阶主题。
指针与引用的关系
指针可重新绑定、可为空;引用是别名且必须绑定对象。许多 API 用 const T& 传参,需要可选或重绑定时才用指针。二者可配合:int& r = *p; 在 p 非空时成立。
本节说明了指针存地址、& 取址、* 解引用及 const 限定。下一节介绍引用:别名语义与函数参数传递。