(delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)

5.5 什么是指针?

​ 指针是 Object Pascal 语言的另一种基本数据类型。一些面向对象的语言在很大程度上隐藏了指针这种强大但危险的语言结构,而 Object Pascal 则允许程序员在需要时使用指针(一般情况下并不经常使用)。

​ 那么什么是指针,这个名字又从何而来呢?与大多数其他数据类型不同的是,指针并不保存实际值,而是保存对变量的间接引用,而变量反过来又有一个值。一种更专业的表述方式是,指针类型定义了一个变量,该变量持有给定数据类型(或未定义类型)的另一个变量的内存地址。

注解:这是本书的一个高级章节,放在这里是因为指针是 Object Pascal 语言的一部分,应该成为任何开发人员的核心知识的一部分,尽管指针不是一个基础的主题,如果你是语言的新手,你可能想在第一次阅读本书时跳过这一部分。同样,你也有可能使用过没有(显式)指针的编程语言,所以这一小部分可能是一次有趣的阅读。

​ 指针类型的定义不是基于特定的关键字,而是使用一个特殊符号—插入符(^)。例如,你可以用下面的声明定义一个表示指向 Integer 类型变量的指针的类型:

type
  TPointerToInt = ^Integer;

​ 一旦您定义了指针变量,可以使用 @ 运算符将另一个变量的地址进行赋值给指针变量:

var
  P: ^Integer;
  X: Integer;
begin
  X := 10;
  P := @X;
  // 使用指针更改X的值
  P^ := 20;
  Show('X: ' + X.ToString);
  Show('P^: ' + P^.ToString);
  Show('P: ' + UIntPtr(P).ToHexString(8));

​ 这段代码是 PointersTest 示例的一部分。在指针 P 指向变量 X 的情况下,您可以使用 P^ 指向变量的值,并读取或更改它。通过使用特殊类型 UIntPtr 将指针转换为数字,还可以显示指针本身的值,即 X 的内存地址(更多信息,请参阅下面的注释)。代码没有显示简单的数值,而是显示了十六进制表示法,这在内存地址中更为常见。这就是输出结果(指针地址可能取决于具体的编译):

X: 20
P^: 20
P: 0018FC18

警告:只有在限制为 2GB 的 32 位平台上,将指针转换为整数才是正确的。如果要使用更大的内存空间,就必须使用 Cardinal 类型。对于 64 位平台,更好的选择是使用 NativeUInt。不过,这种类型有一个别名,专门用于指针,称为 UIntPtr,它是这种情况下的最佳选择,因为使用它可以向开发人员和编译器清楚地表明你的意图。

为了清晰起见,让我总结一下。当您有一个指针 P 时:

  • 通过直接使用指针(使用表达式 P)可以引用指针所指向的内存的地址。
  • 通过解引用指针(使用表达式 P^)可以引用该内存位置的实际内容。

指针也可以不引用现有的内存位置,而是引用通过 New 过程在堆上动态分配的新的特定内存块。在这种情况下,当你不再需要指针访问的值时,你也必须通过调用 Dispose 来删除动态分配的内存。

注解:内存管理和堆的工作方式在第13章中有详细介绍。简而言之,堆是一块(很大的)内存区域,在堆中你不用按指定顺序分配和释放内存块。除了 New 和 Dispose 之外,还可以使用 GetMem 和 FreeMem,它们要求开发人员提供分配的大小(而在 New 和 Dispose 的情况下,编译器会自动确定分配的大小)。在编译时不知道分配大小的情况下、 GetMem 和 FreeMem 就变得非常方便。

下面是一段动态分配内存的代码片段:

var
  P: ^Integer;
begin
  // 初始化
  New(P);
  // 操作
  P^ := 20;
  Show(P^.ToString);
  // 终止
  Dispose(P);

如果在使用内存后为释放,程序最终可能会耗尽所有可用内存并崩溃。未释放不再需要的内存被称为内存泄漏。

警告:为了更安全起见,上面的代码实际上应该使用 try-finally 块,我决定在本书的这个部分不介绍这个主题,但我会在后面的第 9 章中介绍。

如果指针没有值,可以为其赋值为 nil。您可以通过直接相等测试或使用 Assigned 函数(如下所示)来测试指针是否为 nil,以确定它当前是否指向某个值。

这种测试经常使用,因为解引用无效指针会导致内存访问违规(根据操作系统的不同,影响也略有不同):

var
  P: ^Integer;
begin
  P := nil;
  Show(P^.ToString);

您可以通过运行PointersTest示例来查看代码的运行效果。您将看到的错误(在Windows上)应该类似于:

Access violation at address 0080B14E in module 'PointersTest.exe'. Read
of address 00000000.

使指针数据访问更安全的方法之一是添加 "指针不为空 "安全检查,例如下面的方法:

if P <> nil then
  Show(P^.ToString);

正如我前面提到的,出于可读性的考虑,另一种通常更可取的方法是使用 Assigned 伪函数:

if Assigned(P) then
  Writeln(P^.ToString);

注解: Assigned 并不是一个真正的函数,因为它是由编译器 "解析 "并生成正确代码的。此外,它还可以用于过程类型变量(或方法引用),而不实际调用它,只是检查它是否被赋值。

​ Object Pascal 还定义了指针数据类型,它表示无类型的指针(如 C 语言中的 void*)。如果使用无类型指针,则应使用 GetMem 而不是 New,并指出要分配的字节数,因为从类型本身无法推断出该值。每次分配的内存变量大小未定义时,都需要使用 GetMem 过程。

​ 在 Object Pascal 中很少需要指针,这是该语言的一个有趣的优点。不过,指针功能在实现一些极其高效的底层函数和调用操作系统的 API 时,还是有所帮助的。无论如何,了解指针对于高级编程和全面理解 Delphi 的对象模型(在幕后使用指针(通常称为引用))都非常重要。

警告: 当一个变量持有指向第二个变量的指针,而第二个变量离开作用域或被释放(如果是动态分配)时,指针将指向未定义或持有其他数据的内存位置。这会导致很难发现的错误。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/407806.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Springboot的校园求职招聘系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的校园求职招聘系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

剪辑视频调色怎么让画质变得清晰 视频剪辑调色技巧有哪些方面 剪辑视频免费的软件有哪些 会声会影调色在哪里 会声会影模板素材

视频调色的作用有很多&#xff0c;除了进行风格化剪辑以外&#xff0c;还可以让作品的画质变得清晰。通过调色来增强画面的清晰度&#xff0c;在观感上也会显得十分自然。视频调色的技巧有很多&#xff0c;并且原理大都十分简单。有关剪辑视频调色怎么让画质变得清晰&#xff0…

神经网络系列---感知机(Neuron)

文章目录 感知机(Neuron)感知机(Neuron)的决策函数可以表示为&#xff1a;感知机(Neuron)的学习算法主要包括以下步骤&#xff1a;感知机可以实现逻辑运算中的AND、OR、NOT和异或(XOR)运算。 感知机(Neuron) 感知机(Neuron)是一种简单而有效的二分类算法&#xff0c;用于将输入…

MATLAB环境下基于NLEO的算法的脑电EEG信号自发活动瞬态检测

自发脑电信号是一种非平稳性很强的随机信号。在传统的脑电信号处理中&#xff0c;较公认的处理方法大多是建立在假设脑电图是准平稳信号的基础上&#xff0c;即认为它可以分成若干段&#xff0c;每一段的过程基本平稳&#xff0c;但段上叠加着瞬态。瞬态信号是有别于背景节率&a…

leetcode:491.递增子序列

1.误区&#xff1a;不能直接对数组排序再求解子集&#xff0c;因为那样就改变了原有数组的顺序 2.树形结构&#xff1a;一个一个取数&#xff0c;然后保证是递增序列&#xff0c;且不能重复。&#xff08;数层上不可以重复取&#xff0c;树枝上可以重复取&#xff09;收集的结…

使用PM2实现高效的应用监控与管理

微信搜索“好朋友乐平”关注公众号。 1. pm2 PM2 是一个流行的进程管理器&#xff0c;用于 Node.js 应用程序。它支持应用程序的负载均衡、自动重启、日志管理、监控以及多环境管理等功能。PM2让开发者能够以守护进程的方式运行和管理 Node.js 应用&#xff0c;即使在应用崩溃…

This dependency was not found解决方法

问题如上(前端代码)&#xff0c;我是引用js文件出的问题&#xff0c;无法找到api/userManage模块。 解决&#xff1a;没感觉哪有问题&#xff0c;把后面加了个/&#xff0c;就解决了&#xff0c;代表src目录&#xff0c;应该是目录和目录之间应该有/作为分割&#xff1a;

计算机网络-局域网

文章目录 局域网局域网拓扑结构以太网以太网传输介质以太网时隙提高传统以太网带宽的途径以太网帧格式 局域网协议IEEE 802参考模型IEEE802.2协议LLC帧格式及其控制字段LLC提供的三种服务 IEEE 802.3协议IEEE 802.4协议IEEE 802.5协议 高速局域网100M以太网千兆以太网万兆以太网…

数理统计的基本概念

文章目录 前提概念性质常用的统计量 前提概念 与概率论的区别&#xff0c;他是基于实际数据的&#xff0c;但是概率是理论计算的结果。 总体&#xff1a;与所研究问题相关的对象的全体。 样本&#xff1a;按照一定的规定&#xff08;每个个体被抽中的概率相同&#xff09;&…

C/C++暴力/枚举/穷举题目(刷蓝桥杯基础题的进!)

目录 前言 一、百钱买百鸡 二、百元兑钞 三、门牌号码&#xff08;蓝桥杯真题&#xff09; 四、相乘&#xff08;蓝桥杯真题&#xff09; 五、卡片拼数字&#xff08;蓝桥杯真题&#xff09; 六、货物摆放&#xff08;蓝桥杯真题&#xff09; 七、最短路径&#xff08;蓝…

人工智能 — 特征选择、特征提取、PCA

目录 一、特征选择1、定义2、原因3、做法4、生成过程5、停止条件 二、特征提取三、PCA 算法1、零均值化&#xff08;中心化&#xff09;2、方差3、协方差4、协方差矩阵5、对协方差矩阵求特征值、特征矩阵6、对特征值进行排序7、评价模型8、代码实现9、sklearn 库10、鸢尾花实例…

MySQL死锁产生的原因和解决方法

一.什么是死锁 要想知道MYSQL死锁产生的原因,就要知道什么是死锁?在了解什么是死锁之前,先来看一个概念:线程安全问题 1.线程安全问题 1.1什么是线程安全问题 线程安全问题&#xff0c;指的是在多线程环境当中&#xff0c;线程并发访问某个资源&#xff0c;从而导致的原子性&a…

编译原理之LR分析

1.LR(0)项目集规范组的构造 构成识别一个文法构造的DFA项目集的全体叫做这个文法的LR&#xff08;0&#xff09;项目集规范族&#xff08;列表法&#xff09; 2.LR(0)项目 如果U :: ub 是文法G的一个规则&#xff0c;其中u或v可为空串&#xff0c;则U—>u.v是G的一个LR(0…

容器镜像详解

1. 镜像组成 一个标准的OCI容器镜像由index, manifest, config, image layers这几个部分组成。 以docker镜像为例&#xff0c;下载的镜像文件保存在/var/lib/docker/目录下面 image/overlay2子目录下面保存着镜像相关的一些元数据 在下面的介绍主要以nginx:latest镜像为例子…

数据结构与算法相关题解20240225

数据结构与算法相关题解20240225 一、58. 最后一个单词的长度二、48. 旋转图像三、69. x 的平方根四、50. Pow(x, n) 一、58. 最后一个单词的长度 简单 给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度…

Mysql运维篇(四) MHA

大佬博文 https://www.cnblogs.com/gomysql/p/3675429.html MySQL 高可用&#xff08;MHA&#xff09; - 知乎 一、MHA简介&#xff1a; MHA&#xff08;Master High Availability&#xff09;目前在MySQL高可用方面是一个相对成熟的解决方案&#xff0c;它由日本DeNA公司y…

回归预测 | Matlab实现SSA-BiLSTM-Attention麻雀算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测

回归预测 | Matlab实现SSA-BiLSTM-Attention麻雀算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测 目录 回归预测 | Matlab实现SSA-BiLSTM-Attention麻雀算法优化双向长短期记忆神经网络融合注意力机制多变量回归预测预测效果基本描述程序设计参考资料 预测效果 基…

MFC由初值终值步长生成数值序列

matlab的冒号运算符可以生成数值序列; 下面来生成自己的数值序列; vc6新建一个对话框工程; 放几个控件;添加成员变量如下; void CMycolonDlg::OnButton1() {// TODO: Add your control notification handler code hereUpdateData(TRUE);double d1, d2;CString str1, …

学习Markdown

https://shadows.brumm.af 欢迎使用Markdown编辑器 你好&#xff01; 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章&#xff0c;了解一下Markdown的基本语法知识。 新的改变 我们对Markdown编辑器进行了一些…

弱引用与C++智能指针

笔试题遇到了弱引用&#xff0c;但是C标准库是没有这个概念的&#xff0c;学了智能指针但是没有听说过弱引用&#xff0c;因此总结一下两者 学习视频链接来自B站 https://www.bilibili.com/video/BV1gV4y1G7fH?p2&vd_sourcefa4ef8f26ae084f9b5f70a5f87e9e41b智能指针 C的…