当前位置: 首页 > news >正文

【C++】--指针与引用深入解析和对比

🔥个人主页:@草莓熊Lotso

🎬作者简介:C++研发方向学习者

📖个人专栏: 《C语言》 《数据结构与算法》《C语言刷题集》《Leetcode刷题指南》

⭐️人生格言:生活是默默的坚持,毅力是永久的享受。

前言:通过前面的学习,我们会发现指针和引用是两个强大而又容易混淆的概念。它们都提供了间接访问变量的方式,但在语法和语义上存在重要差异,所以博主在这里想给大家详细讲解一下指针和引用的使用,特点以及对比分析。


目录

一.指针和引用的概念

二.指针与引用的核心区别

1. 声明与初始化

2. 可修改性

3. 空值

4. 内存占用

5. 操作符

6. 多级访问

三.指针与引用的共同点

何时使用指针,何时使用引用?

使用引用的场景:

使用指针的场景:


一.指针和引用的概念

指针:指针是一个变量,其值为另一个变量的内存地址。我们可以通过指针来间接访问和修改它所指向的变量的值。

int main() {int x = 10;int* ptr = &x;  // 指针ptr指向x的地址cout << "x的值: " << x << endl;       // 直接访问xcout << "x的地址: " << &x << endl;    // 输出x的地址cout << "ptr的值: " << ptr << endl;   // 输出ptr存储的地址(即x的地址)cout << "ptr指向的值: " << *ptr << endl;  // 通过指针访问x的值*ptr = 20;  // 通过指针修改x的值cout << "修改后x的值: " << x << endl;return 0;
}

引用:引用是已存在变量的别名,它与被引用的变量共享同一内存地址。引用一旦初始化后,就不能再指向其他变量。

int main() {int x = 10;int& ref = x;  // ref是x的引用(别名)cout << "x的值: " << x << endl;cout << "ref的值: " << ref << endl;cout << "x的地址: " << &x << endl;cout << "ref的地址: " << &ref << endl;  // 与x的地址相同ref = 20;  // 通过引用修改x的值cout << "修改后x的值: " << x << endl;return 0;
}

二.指针与引用的核心区别

1. 声明与初始化

  • 指针:使用*声明,可以不初始化(但不推荐),也可以初始化为nullptr
int* ptr1;       // 未初始化的指针(危险)
int* ptr2 = nullptr;  // 空指针
int x = 5;
int* ptr3 = &x;  // 指向x的指针
  • 引用:使用&声明,必须在创建时初始化,且不能初始化为nullptr
int x = 5;
int& ref1 = x;   // 正确,ref1是x的引用
// int& ref2;    // 错误,引用必须初始化
// int& ref3 = nullptr;  // 错误,不能将引用初始化为空

2. 可修改性

  • 指针:可以改变指向的对象
int x = 5, y = 10;
int* ptr = &x;
ptr = &y;  // 指针现在指向y
  • 引用:一旦绑定到某个对象,就不能再绑定到其他对象
int x = 5, y = 10;
int& ref = x;
ref = y;  // 这是将y的值赋给x,而不是让ref引用y

3. 空值

  • 指针:可以为空(nullptr),表示不指向任何对象
int* ptr = nullptr;  // 空指针
  • 引用:不能为空,必须始终引用一个有效的对象。不存在 "空引用" 的概念

4. 内存占用

  • 指针:需要占用内存空间来存储地址(通常为 4 字节或 8 字节,取决于系统)

  • 引用:在语法层面不占用内存空间,它只是一个别名。编译器通常会使用指针来实现引用,但这是编译器内部的事情,对程序员是透明的。

5. 操作符

  • 指针:使用*运算符访问指向的对象,使用->运算符访问指向对象的成员
struct Person {string name;int age;
};Person p{"Alice", 30};
Person* ptr = &p;
cout << ptr->name << endl;  // 使用->访问成员
cout << (*ptr).age << endl; // 先解引用再用.访问成员
  • 引用:直接使用.运算符访问成员,无需解引用
Person p{"Bob", 25};
Person& ref = p;
cout << ref.name << endl;  // 直接使用.访问成员

6. 多级访问

  • 指针:支持多级指针(指针的指针)

    int x = 5;
    int* ptr = &x;
    int**ptr_ptr = &ptr;  // 指向指针的指针
    cout << ** ptr_ptr << endl;  // 输出5

  • 引用:不支持多级引用,不存在 "引用的引用"


三.指针与引用的共同点

  1. 都可以间接访问和修改所指向 / 引用的变量
  2. 都可以作为函数参数,实现参数的 "传址" 效果,允许函数修改实参的值
  3. 都可以指向 / 引用堆上分配的内存

何时使用指针,何时使用引用?

使用引用的场景:

  1. 函数参数传递,尤其是对于大型对象,可以避免拷贝开销,同时不希望参数为 null
  2. 函数返回值,当函数需要返回容器元素或对象成员的访问权时
  3. 操作符重载(如operator=),使语法更自然
// 引用作为函数参数
void swap(int& a, int& b) {int temp = a;a = b;b = temp;
}// 引用作为函数返回值
vector<int> vec = {1, 2, 3};
int& get_element(int index) {return vec[index];  // 返回向量元素的引用
}

使用指针的场景:

  1. 需要表示 "空" 的情况(可以使用nullptr
  2. 需要改变指向的目标时
  3. 处理动态分配的内存
  4. 实现数据结构(如链表、树等)
  5. 函数需要返回多个值时(通过指针参数)
// 指针表示空值
int* find(int* arr, int size, int target) {for (int i = 0; i < size; i++) {if (arr[i] == target) {return &arr[i];}}return nullptr;  // 未找到,返回空指针
}// 动态内存分配
int* create_array(int size) {return new int[size];  // 返回指向新分配数组的指针
}

指针和引用都是 C++ 中用于间接访问变量的重要工具,它们各有特点和适用场景:

  • 指针更灵活,可以为空,可以改变指向,但使用不当容易引发错误
  • 引用更安全,必须初始化且不能为 null,语法更简洁,但灵活性较低

往期回顾:

结语:本篇博客给大家分享了指针和引用的对比分析以及各自的使用场景,理解指针和引用的区别,以及它们各自的适用场景,是编写高效、安全的 C++ 代码的基础。在实际编程中,应根据具体需求选择合适的工具,遵循 "能用引用就用引用,需要指针特性时再用指针" 的原则。如果文章对你有帮助的话,欢迎评论,点赞,收藏加关注,感谢大家的支持。

http://www.xdnf.cn/news/1330813.html

相关文章:

  • 2025 | 腾讯混元RLVMR颠覆强化学习:可验证推理奖励引爆AI智能体新范式!
  • 文本智能抽取:如何用NLP从海量文本中“炼“出真金?-告别无效阅读,让AI成为你的“信息炼金师
  • git 生成 Patch 和打 Patch
  • 在完全没有无线网络(Wi-Fi)和移动网络(蜂窝数据)的环境下,使用安卓平板,通过USB数据线(而不是Wi-Fi)来控制电脑(版本2)
  • 汽车ECU实现数据安全存储(机密性保护)的一种方案
  • 网页作品惊艳亮相!这个浪浪山小妖怪网站太治愈了!
  • uni-app跨端开发最后一公里:详解应用上架各大应用商店全流程
  • 云计算学习100天-第26天
  • 《CDN加速的安全隐患与解决办法:如何构建更安全的网络加速体系》
  • 【Ansible】变量、机密、事实
  • Ubuntu-安装Epics Archiver Appliance教程
  • ansible playbook 实战案例roles | 实现基于firewalld添加端口
  • 如何使用matlab将目录下不同的excel表合并成一个表
  • 四川方言语音识别数据集,1500小时合规真人采集,高质量标注助力ASR与大模型训练
  • CISP-PTE之路--10文
  • java17学习笔记
  • python numpy.random的基础教程(附opencv 图片转数组、数组转图片)
  • cv2.bitwise_and是 OpenCV 中用于执行按位与运算的核心函数,主要用于图像处理中的像素级操作
  • 计算机视觉 图片处理 在骨架化过程中,每次迭代都会从图像的边缘移除一层像素,直到只剩下单像素宽度的骨架
  • 【图像算法 - 19】慧眼识苗:基于深度学习与OpenCV的大棚农作物生长情况智能识别检测系统
  • Kubernetes集群安装部署--flannel
  • InnoDB为什么使用B+树实现索引?
  • 从繁琐到优雅:Java Lambda 表达式全解析与实战指南
  • 【Spring Boot把日志记录到文件里面】
  • sfc_os!SfcQueueValidationRequest函数分析之sfc_os!IsFileInQueue
  • Android面试指南(三)
  • STM32学习笔记15-SPI通信软件控制
  • 《Java 多线程全面解析:从基础到生产者消费者模型》
  • InfoNES模拟器HarmonyOS移植指南
  • 从数据孤岛到实时互联:Canal 驱动的系统间数据同步实战指南