引用和指针有什么区别 两种间接访问方式对比

指针是存储地址的变量,可重新赋值和为空,支持算术运算;引用是变量别名,必须初始化且不可重绑定,更安全简洁,常用于函数参数和操作符重载。

引用和指针都能实现间接访问变量,但它们在语法、使用方式和底层机制上有明显不同。理解这些差异有助于写出更安全、高效的C++代码。

定义与初始化

指针是一个变量,存储的是另一个变量的内存地址。它可以被声明后不立即初始化,也可以在程序运行过程中指向不同的对象。

int a = 10;
int* ptr = &a; // 指针指向a的地址
ptr = nullptr; // 可以被设为空或重新赋值

引用是某个已存在变量的别名,必须在声明时初始化,且一旦绑定就不能再指向其他变量。

int a = 10;
int& ref = a; // ref是a的别名
// ref = b; // 错误:不能重新绑定引用

内存与操作方式

指针本身有独立的内存空间,存储的是地址值。你可以对指针进行算术运算(如ptr++),也可以有多级指针(如int**)。

int arr[5] = {1,2,3,4,5};
int* p = arr;
p++; // 指向下一个元素

引用不占用额外的“对象级”内存概念(编译器通常用指针实现引用,但对程序员透明),不能进行算术操作,也不支持多级引用(虽然有引用的引用,但会被折叠)。

int& r = a;
// r++; // 操作的是a的值,不是地址移动

空值与安全性

指针可以为空(nullptr),这在函数返回失败或可选对象时非常有用,但也带来了空指针解引用的风险。

int* ptr = nullptr;
if (ptr) { /* 安全检查 */ }

引用必须绑定到一个有效对象,不能为“空”。一旦引用被创建,它就始终有效(前提是原对象未销毁)。这使得引用更安全,但前提是初始化正确。

int& badRef = *static_cast(nullptr); // 危险,未定义行为

作为函数参数的使用

指针传参明确表示可以修改或为空,常用于C风格接口。

void func(int* p) {
if (p) *p = 20;
}

引用传参更简洁,常用于C++中的输出参数或避免拷贝大对象。

void func(int& r) {
r = 20; // 直接修改原变量
}

引用还能用于实现操作符重载(如operator

基本上就这些。引用更安全、简洁,适合大多数间接访问场景;指针更灵活,适合动态内存、数组操作和可选对象处理。选择哪种方式,取决于具体需求和代码风格。

以上就是引用和指针有什么区别 两种间接访问方式对比的详细内容,更多请关注骃骐网【www.myinqi.com】。

相关推荐:

如何在Python中检测单链表中是否存在环_使用快慢指针(Floyd判圈算法)

快慢指针能检测环是因为有环时相对速度为1,有限步内必相遇;无环时快指针先达None。需检查空链表、单节点、自环等边界条件,循环条件应为while fast and fast.next,用is比较节点,相遇后可求环入口。 快慢指针为什么能检测环 核心在于:如果链表有环,快指针(每次走2步)迟早会追上慢指针(每次走1步);如果无环,快指针必然先走到 None。这不是概率问题,而是数学上的相遇必然性——...

Python中global与nonlocal关键字有什么区别_针对全局作用域与嵌套作用域的赋值

必须用global:在函数内对已存在的模块级变量赋值且需影响全局时;必须用nonlocal:在嵌套函数中修改外层函数的局部变量且该变量非全局也非本层局部时。 global 用于改模块级变量,nonlocal 用于改外层函数的局部变量;写错一个,轻则值不更新,重则直接报 UnboundLocalError 或 SyntaxError。 什么时候必须用 global? 当你在函数内对一个**已经存在的...

Python怎么实现文件内容的倒序读取_利用文件指针跳转到末尾反向搜索

倒序读取大文件应使用seek()和readline()控制文件指针,而非readlines()[::-1]以免OOM;需以'rb'模式打开,从末尾逐字节回退识别换行符,兼容\r\n,用生成器实现内存友好。 用 seek() 和 readline() 从文件末尾倒着读行 直接 readlines()[::-1] 会把整个文件加载进内存,大文件(比如几百 MB 的日志)容易 OOM。真正可行的倒序读取...

Python 使用 Pika 的 basic_consume 方法时 “auto_ack” 参数开启和关闭有什么区别?

auto_ack=True时消息立即确认并删除,不等待业务处理完成;auto_ack=False需手动调用basic_ack,否则消息滞留Unacked状态,适用于高可靠性场景。 auto_ack=True 时消息一发就丢,不等业务处理完 开启 auto_ack=True 意味着 RabbitMQ 在把消息推给消费者后,**立刻标记为已确认并从队列中移除**,不管你的回调函数是否执行完毕、有没有抛...

C++智能指针未来展望 C++23新特性预览

C++23通过std::expected、std::propagate_const等新特性增强智能指针生态,提升资源管理的安全性与代码清晰度,同时引入std::print、if consteval和Lambda显式模板参数,改进错误处理、输出和编译期编程,推动现代C++向更安全高效的开发模式演进。 C++ 的智能指针和新特性一直在演进,目标是让资源管理更安全、更高效,代码更清晰。C++23 带来了...

C++智能指针控制块 内部结构解析

智能指针的控制块是实现共享所有权和自动资源管理的核心机制,尤其在 std::shared_ptr 中起着关键作用。理解其内部结构有助于掌握其性能特征和使用注意事项。 控制块的基本组成 控制块是一个动态分配的结构体,由 std::shared_ptr 在首次创建时生成,用于管理所指向对象的生命周期。它通常包含以下成员: 引用计数(shared reference count):记录当前有多少个 sh...

C++智能指针原理 RAII资源管理机制解析

智能指针通过RAII机制实现内存自动管理,利用对象生命周期控制资源;std::unique_ptr独占所有权,std::shared_ptr引用计数共享资源,std::weak_ptr打破循环引用,三者均在析构时释放内存,避免泄漏。 智能指针的核心在于自动管理动态分配的内存,避免内存泄漏和悬空指针。这背后的关键机制是RAII(Resource Acquisition Is Initializati...

Vue中computed和watch的使用场景有什么区别?

computed 适合基于已有数据同步计算新值,具有缓存机制,适用于格式化文本、过滤数组、判断状态等场景;例如通过 fullname 计算姓氏和名字的拼接。watch 则适合监听数据变化后执行异步或复杂操作,如发送 api 请求、深度监听对象变化,例如监听 searchquery 发起搜索或使用 deep: true 监听 userinfo 的深层变化。选择时应明确用途,生成新数据优先用 comp...

Go语言中避免空指针解引用错误的策略与实践

本文深入探讨了Go语言中空指针解引用(nil pointer dereference)错误的常见原因及其预防策略。通过分析Go的零值概念,并结合具体代码示例,详细阐述了如何通过选择合适的类型(如[]*struct)、显式初始化、以及必要的nil检查等方法,有效地构建健壮且避免运行时panic的Go应用程序。理解Go语言中的空指针解引用 在go语言中,空指针解引用(nil pointer deref...

避免 Go 语言中空指针解引用错误:结构体字段与切片指针的最佳实践

本文深入探讨 Go 语言中常见的空指针解引用(nil pointer dereference)错误,特别是涉及结构体字段和切片指针的场景。通过分析问题代码,提供了一种更符合 Go 语言习惯的解决方案,即使用 []*struct 代替 *[]struct,并强调了 Go 语言零值初始化、显式初始化以及必要时进行 nil 检查等关键实践,旨在帮助开发者编写更健壮、更可靠的代码。在 Go 语言中,空指针...