指针保存对象的地址,通过解引用读写所指内存。C++ 仍保留指针,但日常代码更常组合使用引用、std::vector 与智能指针,以减少裸指针带来的空指针与悬垂风险。本节说明何时仍需要指针、nullptr 与 const 限定,并衔接引用与智能指针;已学过C 语言指针的读者可重点看 C++ 差异列。

指针、引用与容器:怎么选

手段典型用途注意
std::vector 等容器元素个数变化、需要迭代与算法优先于手动 new[]
引用 T&函数参数、运算符重载、别名必须绑定有效对象,不可空
指针 T*可选对象、C API、链表节点、重绑定判空、生命周期、优先智能指针管理堆内存

取地址与解引用

普通变量保存值;指针保存地址。对指针解引用(*)按该地址访问对象;声明里的 * 表示类型为指针,与表达式中的解引用含义不同。

基本规则

  • & 取地址:&value 得到 value 的地址,类型为 int*,可赋给同类型指针。
  • * 解引用:在表达式中对指针使用 *ptr 访问所指对象;声明中的 * 表示该标识符是指针类型,含义不同。
  • 初始化:指针声明后应绑定有效地址或 nullptr;未初始化的指针解引用属于未定义行为。

声明与基本操作

C++ 指针取址与解引用运行
#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";       // 3

p + 1 指向下一个 int,步长为 sizeof(int)。越界指针算术与解引用同样危险。容器场景优先使用 std::vector 与范围 for,见vector。

const 与指针

下列两种写法含义不同,宜对照记忆:

声明形式含义
const int* p 或 int const* p不能通过 p 修改所指 int,可改 p 的指向
int* const pp 本身不可改指向,可通过 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 限定。下一节介绍引用:别名语义与函数参数传递。