从指针到引用
- 来源: https://www.freebasic.net/wiki/wikka.php?wakka=ProPgFromPtrToRef
- 最后更新: 2019-10-11
引用并不完全提供与指针相同的功能,但使用引用可以简化编码。
前言:
引用和指针密切相关。
实际上,变量及其不同的引用持有相同的地址,因为它们允许访问相同的对象。
引用封装了对象地址的操作,并作为已解引用的指针使用。
区别在于不必执行解引用操作。
引用比指针更容易处理,因此使代码更安全。
指针回顾
地址是一个值。用户可以将此值存储在变量中。指针正是包含其他对象地址的变量,例如另一个变量的地址。
指针的值可以改变。这通常不意味着被指向的变量在内存中移动,而是指针指向了其他东西。
为了明确指针指向什么,指针有类型。这种类型通常从被指向对象的类型构建。这允许编译器验证通过指针在内存中进行的操作是否有效。
指针最常见的用途是作为过程的参数传递。它们能够以简单的方式操作可能很重要的数据(不必向过程提供非常大的数据块,可以例如提供指向它的指针)。
另一种用途是在内存中进行动态分配时,使用返回已分配内存地址的 '[C]Allocate' 和 'New' 关键字。这个地址必须存储在某处并知道如何使用它。
最后,指针也可以用于操作表,但在 FB 中其重要性较低,因为用户有能力声明静态和动态数组,并使用专用的 '()' (数组索引)运算符访问其元素。
还可以创建指向过程的指针,并使用这些指针参数化算法,该算法的行为将取决于所指向的过程。
非常重要的是,确保用户正在操作的所有指针都已初始化(即它们包含有效对象的地址,而不是随机内容)。实际上,通过未初始化的指针访问变量,相当于在内存中完全随机的位置进行读取,或更严重地进行写入(根据创建时指针的初始值)。
通常,指针在创建时立即初始化,或者如果要在以后使用,则用空值初始化。这将允许对指针有效性进行未来测试,或至少检测错误。实际上,使用具有空值的指针访问变量通常会产生程序保护错误,但如果使用 '-exx' 选项编译程序,将在运行时始终产生错误消息。
使用解引用运算符 '*' 和 '[]',可以从指针访问变量。
'Any Ptr' 指针是一种特殊类型的指针。它们可以指向任何类型的变量。不能在 'Any Ptr' 指针上使用 '*' 和 '[]' 解引用运算符。必须先将其转换为给定类型的指针。
类似地,类型化指针也可以转换为任何其他类型的指针(如有必要,首先通过 'Any Ptr' 指针转换)。
对于对象指针('po'),使用单个 '->' 运算符比组合 "*" 和 "." 来访问对象成员更方便(使用 'po->member' 而不是 '(*po).member')。
指针也可以声明为与被指向对象的地址类型不同但兼容的类型(作为简单示例,'Zstring Ptr' 和 'Ubyte Ptr' 是两种在两个方向上兼容的指针类型)。以更高级的方式,在继承结构中,派生类型对象可以用从其共同基类类型之一构建的指针引用(当在此类指针上调用虚拟且已重写的方法时,允许激活多态性)。
指针有自己的算术。此类型的递增/递减是特殊的。通过将指针类型的大小乘以要加/减的值来完成。这使得可以将指针向前或向后移动所指示的元素数量。
指针之间唯一允许的操作是减法,前提是指针类型相同。只有当指针指向相同的同构元素结构(指针类型的元素)时,此操作才有意义,因为结果对应于元素数量的差值。
引用的概念
在更高级的语言中,倾向于通过引用和编译器管理的动态数组来取代指针的使用。引用通过移除用户对内存的显式访问来实现某些指针功能。这避免了许多问题,但作为回报,一些用途和优化不再可能。
除了访问内存中表示的数据的两种经典方式:使用其名称(如果它是变量或常量)或解引用包含其地址的指针,还有第三种方法,即引用的使用,在某些情况下这是绝对必要的,并且提供了除了使用指针之外的替代方案。
引用是将新名称与已存在对象关联的方式。
它不是创建新对象的手段,即使创建引用变量的语法看起来奇怪地类似于初始化变量的定义。
这种新名称的分配不会剥夺相关对象的原始名称(如果它有的话)。新名称只是成为旧名称的同义词,这意味着它们都指向同一个对象。
通过引用而不是通过值传递/返回变量,避免了对传输对象进行复制。当相关对象非常大时,复制操作在运行时和内存方面都很昂贵。
像指针一样,引用有自己的类型,必须与被引用对象的类型相同,或者至少兼容。只有在后一种情况下(类型兼容但不相同),引用(像指针一样)不能执行与原始对象相同的所有操作。
使用对象的引用可以获得与使用"对象指针"(速度和内存节省)相关的优势,同时避免了使用对象指针所隐含的书写繁琐(使用 '@' 运算符以及 '*' 或 '[]' 运算符)。
注意:
FB 中目前尚不支持引用数组。
FB 中目前尚不支持 UDT 的非静态引用字段。
FB 中不支持对过程的引用(只支持对过程指针的引用)。
使用引用
请参阅本"引用"部分的下一页:
- '使用引用' 页面。
另请参阅
Allocate、Callocate、New (Expression)Operator @ (Address of)、Operator * (Value of)、Operator [] (Pointer index)Operator . (Member access)、Operator -> (Pointer to member access)- 指针概述
- 指针算术
- 使用引用
返回 目录