C++交换指针的三种实现方式:双重指针、引用及标准库

凌晨两点半
凌晨两点半
发布时间:2026-10-14| 2人浏览过
原创

本文深入解析C++中交换指针变量的正确方法与底层原理。针对实际开发中经常遇到的指针交换需求,详细对比了传统C语言风格的双重指针传参、C++特有的引用传参,以及推荐使用的标准库解决方案。文章提供包含完整可运行代码及终端输出结果的实践案例,帮助开发者理解不同实现方式的差异并选择最优路径。

为什么需要单独交换指针?

在处理普通整型或对象数据时,直接交换其值即可。但在处理指针(内存地址)时,我们的目标往往是让指针pa和pb指向彼此的原始目标内存,而不是去交换它们所指向内容的数据。

// 交换的是整型的值
void swap_int(int *a, int *b) {
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

上述代码仅改变了指针所指向的值,指针本身的地址(如 &a 和 &b)并未互换。若目标是让 pa 指向原来 pb 指向的变量,我们需要交换指针本身,而非它们解引用的值。

方法一:使用双重指针(C语言风格)

这是最基础也最容易出错的方式。要修改指针变量本身,必须将该指针的地址传递给函数。因此函数的形参需要是“指向指针的指针”(双重指针),调用时传入取地址符 &。

核心逻辑:函数内部接收的是指针的副本地址,通过解引用双重指针来获取并交换原始指针的值。

void ptrSwap_Pointer(int **a, int **b) {
    int *tmp = *a; // 获取a指向的指针值
    *a = *b;       // 将b指向的指针值赋给a
    *b = tmp;      // 将暂存的旧值赋给b
}

以下是完整的测试代码及执行结果截图:

#include <iostream>
using namespace std;

// 使用双重指针交换
void ptrSwap_Pointer(int **a, int **b) {
    int *tmp = *a;
    *a = *b;
    *b = tmp;
}

int main() {
    int a = 10, b = 20;
    int *pa = &a, *pb = &b;

    cout << "Swap before:\n";
    cout << "Value: a = " << a << ", b = " << b << endl;
    cout << "Pointer: pa = " << pa << ", pb = " << pb << endl;

    // 关键点:必须传递指针本身的地址 &pa 和 &pb
    ptrSwap_Pointer(&pa, &pb);

    cout << "\nSwap after (Pointer method):\n";
    cout << "Value: a = " << a << ", b = " << b << endl;
    cout << "Pointer: pa = " << pa << ", pb = " << pb << endl;
    return 0;
}

结果说明:

从输出结果可以看出,执行完函数后,变量 a 和 b 中的数值依然保持 10 和 20 不变。但是,指针 pa 现在的值等于原 pb 的值,pb 变成了原 pa 的值。这证明了通过双重指针成功交换了指针所保存的地址信息。

第1步:定义带有双重指针参数的函数

目的:准备接收指针的地址,以便在内层解引用后直接操作原始的指针变量。 入口:创建一个返回 void 的函数,参数声明为 int **pa 和 int **pb。 动作:使用临时指针变量 int *tmp 进行三个赋值操作完成互换。 重要参数:确保调用时传入的是 &ptr_name,而非 ptr_name。 完成状态:编写无编译错误的交换函数主体。

第2步:在主程序中分配指针并调用

目的:验证函数是否能正确改变指针的指向。 入口:main 函数。 动作:初始化两个整型变量及其对应的指针。打印初始状态。然后调用交换函数,注意传入 &pa。
重要参数:需关注 <iostream> 的使用以确保控制台输出可见。 完成状态:终端显示交换前后的地址变化,证明指针已互换。

方法二:使用引用(C++风格)

C++提供了一种更优雅且直观的方案:使用引用。由于我们要交换的是指针变量本身,所以需要“指向指针的引用”。语法上:int *&pa。

语法规则分解:
从左往右看:这是一个引用 (&),它引用的是一个指向 int 类型的指针 (*)。这样我们就可以像操作普通变量一样操作这个被引用的指针。

void ptrSwap_Reference(int *&pi, int *&pj) {
    int *pk = pi;
    pi = pj;
    pj = pk;
}

调用时非常简单,直接传入指针变量名即可:

int *pi = &i;
int *pj = &j;
ptrSwap_Reference(pi, pj); // 直接使用,无需取地址符

第1步:定义带有指针引用参数的函数

目的:利用C++引用机制简化函数签名。
入口:创建新的交换函数,参数类型为 int *&。 动作:标准的三行代码逻辑:临时持有、替换A、还原B。
重要参数:形参必须是引用类型 &,否则只是修改局部拷贝。
完成状态:函数能够直接接受外部传入的指针实参。

第2步:在主程序中分配指针并调用

目的:验证引用方式的效果并与第一种方法进行对比。
入口:main 函数。 动作:定义指针,调用 ptrSwap_Reference(pi, pj)。
重要参数:此处**不需要**也不应该使用 & 符号传给形参。
完成状态:交换前后指针的打印结果显示地址发生了正确的互换。

方法三:使用 C++ 标准库 std::swap(最佳实践)

在实际项目开发中,除了手动实现,通常建议直接使用 C++ STL 提供的模板函数。它不仅写法最简洁,而且具备类型安全检查和潜在的优化机制。

#include <utility> // 现代C++通常在iostream包含它,但显式引入更好
#include <iostream>

int main() {
    int *pa = new int(10);
    int *pb = new int(20);

    // 只需一行代码
    std::swap(pa, pb);

    delete pa;
    delete pb;
    return 0;
}

第1步:包含必要的头文件并初始化资源

目的:构建一个适合演示 std::swap 的运行环境。 入口:main 函数头部。 动作:定义两个具有相同类型(例如都是 int*)的指针变量。
重要参数:确保两个待交换变量的类型完全一致。
完成状态:定义了类型匹配的 pa 和 pb。

第2步:调用模板函数并观察结果

目的:通过标准接口完成互换,避免手写逻辑带来的潜在风险(如遗漏清理)。 入口:使用 std::swap() 函数。 动作:直接传递两个指针的标识符。 重要参数:无需额外配置,编译器会自动推导类型。 完成状态:指针 pa 现在指向了原先 pb 指向的对象。

排错指南:指针未发生交换的常见原因

当开发者尝试交换指针时发现无效,通常是以下两种逻辑导致的:

  • 使用了单级指针作为参数:如果函数定义为 void swap(int *a, int *b),那么你在里面做的任何对 a 或 b 的赋值(如 a=b),都只是改变了函数内部的局部副本指针。一旦函数返回,外部的真实指针不会改变。解决方法是使用双重指针或引用。
  • 错误地交换了内容:如果在双/单层指针函数里写了 *a = *b,那交换的是它们指向的目标数值,而指针地址本身没有变。请始终确认你的意图是改变指针地址还是目标数据。

总结

无论是使用C风格的间接寻址,还是C++风格的引用特性,亦或是现代C++推荐的模板算法,理解它们之间的区别对于掌握底层内存操作至关重要。在工程实践中,优先推荐使用 std::swap,因为它不仅语义清晰,还能有效防止忘记释放内存等严重Bug的发生。 以上就是C++交换指针方法的详细内容,更多关于C++指针应用及优化的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。