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. 注意事项与最佳实践

  1. 尽量使用智能指针unique_ptr/shared_ptr)管理动态内存,避免手动 new/delete
  2. 检查空指针nullptr)后再解引用,避免崩溃。
  3. 避免过度指针算术,出错率高且可读性差,推荐使用标准容器(如 std::vector)和迭代器。
  4. 函数参数传递:若要修改指针本身,可用指向指针的指针;否则优先使用引用或智能指针。

通过掌握以上各类指针用法,你就能在 C++ 中高效、安全地进行底层内存操作与资源管理。

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注