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

5.5 什么是指针?

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

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

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

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

typeTPointerToInt = ^Integer;

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

varP: ^Integer;X: Integer;
beginX := 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 就变得非常方便。

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

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

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

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

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

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

varP: ^Integer;
beginP := nil;Show(P^.ToString);

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

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

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

if P <> nil thenShow(P^.ToString);

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

if Assigned(P) thenWriteln(P^.ToString);

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

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

密码算法简单整理

密码组成 国外的密码算法&#xff1a; DES、3DES、AES、SHA1、SHA2、SHA3、DSA、RSA、RC4等 高危密码算法&#xff1a; MD5、DES、RSA1024以下、SSH1.0、SSL3.0以下、SHA1等 密码算法通常可分为三大类&#xff1a; 对称密码算法 非对称密码算法 密码杂凑算法 1.对称密码算法&am…

LeetCode 1637.两点之间不包含任何点的最宽垂直区域

给你 n 个二维平面上的点 points &#xff0c;其中 points[i] [xi, yi] &#xff0c;请你返回两点之间内部不包含任何点的 最宽垂直区域 的宽度。 垂直区域 的定义是固定宽度&#xff0c;而 y 轴上无限延伸的一块区域&#xff08;也就是高度为无穷大&#xff09;。 最宽垂直区…

udp服务器【Linux网络编程】

目录 一、UDP服务器 1、创建套接字 2、绑定套接字 3、运行 1&#xff09;读取数据 2&#xff09;发送数据 二、UDP客户端 创建套接字&#xff1a; 客户端不用手动bind 收发数据 处理消息和网络通信解耦 三、应用场景 1、服务端执行命令 2、Windows上的客户端 3…

掌控互联网脉络:深入解析边界网关协议(BGP)的力量与挑战

BGP简介 边界网关协议&#xff08;Border Gateway Protocol&#xff0c;BGP&#xff09;是互联网上最重要的路由协议之一&#xff0c;负责在不同自治系统&#xff08;AS&#xff09;之间传播路由信息。BGP使得互联网中的不同网络可以互相通信&#xff0c;支持互联网的规模化扩…

2278. 企鹅游行(最大流,拆点)

活动 - AcWing 在南极附近的某个地方&#xff0c;一些企鹅正站在一些浮冰上。 作为群居动物&#xff0c;企鹅们喜欢聚在一起&#xff0c;因此&#xff0c;它们想在同一块浮冰上会合。 企鹅们不想淋湿自己&#xff0c;所以它们只能利用自己有限的跳跃能力&#xff0c;在一块块…

UnityWebGL 设置全屏

这是Unity导出Web默认打开的页面尺寸 修改后效果 修改 index.html 文件 1.div元素的id属性值为"unity-container"&#xff0c;宽度和高度都设置为100%&#xff0c;意味着该div元素将占据整个父容器的空间。canvas元素的id属性值为"unity-canvas"&#xff…

Llama中文大模型-模型部署

​​​​​​选择学习路径 快速上手-使用Anaconda 第 0 步&#xff1a;前提条件 确保安装了 Python 3.10 以上版本。 第 1 步&#xff1a;准备环境 如需设置环境&#xff0c;安装所需要的软件包&#xff0c;运行下面的命令。 git clone https://github.com/LlamaFamily/Ll…

论文阅读——SimpleClick

SimpleClick: Interactive Image Segmentation with Simple Vision Transformers 模型直接在VIT上增加交互是分割 用VIT MAE方法训练的预训练权重 用交互式分割方法微调&#xff0c;微调流程&#xff1a; 1、在当前分割自动模拟点击&#xff0c;没有人为提供的点击 受到RITM启发…

uni-app nvue vue3 setup中实现加载webview,解决nvue中获取不到webview实例的问题

注意下面的方法只能在app端使用&#xff0c; let wv plus.webview.create("","custom-webview",{plusrequire:"none", uni-app: none, width: 300,height:400,top:uni.getSystemInfoSync().statusBarHeight44 }) wv.loadURL("https://ww…

1003: 【C1】【一维数组】【入门】统计

题目描述 给出n个整数和k&#xff0c;统计其中有多少个整数和k相等。 输入 第一行为1个整数 n &#xff08;1 < n < 1000 &#xff09;&#xff0c;整数的个数。 之后 的n 行&#xff0c;每行1个整数。 最后一行&#xff0c;1个整数k。 输出 一个整数&#xff0c;表…

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

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

基于springboot+vue的精准扶贫管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

中国农业无人机行业市场现状分析与投资前景预测研究报告

全版价格&#xff1a;壹捌零零 报告版本&#xff1a;下单后会更新至最新版本 交货时间&#xff1a;1-2天 第一章农业无人机行业发展综述 第一节农业无人机行业定义及分类 一、农业无人机行业的定义 农业无人机是一种无人驾驶的飞行器来帮助优化农业经营&#xff0c;增加作…

[rust] 11 所有权

文章目录 一 背景二 Stack 和 Heap2.1 Stack2.2 Heap2.3 性能区别2.4 所有权和堆栈 三 所有权原则3.1 变量作用域3.2 String 类型示例 四 变量绑定背后的数据交互4.1 所有权转移4.1.1 基本类型: 拷贝, 不转移所有权4.1.2 分配在 Heap 的类型: 转移所有权 4.2 Clone(深拷贝)4.3 …

C++基础知识(六:继承)

首先我们应该知道C的三大特性就是封装、继承和多态。 此篇文章将详细的讲解继承的作用和使用方法。 继承 一个类&#xff0c;继承另一个已有的类&#xff0c;创建的过程 父类(基类)派生出子类(派生类)的过程 继承提高了代码的复用性 【1】继承的格式 class 类名:父类名 {}; 【…

SpringMVC 学习(三)之 @RequestMapping 注解

目录 1 RequestMapping 注解介绍 2 RequestMapping 注解的位置 3 RequestMapping 注解的 value 属性 4 RequestMapping 注解的 method 属性 5 RequestMapping 注解的 params 属性&#xff08;了解&#xff09; 6 RequestMapping 注解的 headers 属性&#xff08;了解&…

Linux安装jdk、tomcat、MySQL离线安装与启动

一、JDK和Tomcat的安装 1.JDK安装 直接上传到Linux服务器的&#xff0c;上传jdk、tomcat安装包 解压JDK安装包 //解压jdk tar -zxvf jdk-8u151-linux-x64.tar.gz 置环境变量(JAVA_HOME和PATH) vim /etc/profile 在文件末尾添加以下内容&#xff1a; //java environment expo…

算法训练营day33(补),动态规划1

// 509. 斐波那契数 func fib(n int) int { if n < 2 { return n } return fib(n-1) fib(n-2) } // 70. 爬楼梯, 本质上就是斐波那契数列但是用递归法&#xff0c;力扣提交会超时 func climbStairs(n int) int { if n < 2 { return n } a, b, sum : 1, 2, 0 for i …

C++面试:物理内存和虚拟内存

目录 物理内存&#xff08;Physical Memory&#xff09; 虚拟内存&#xff08;Virtual Memory&#xff09; windows是如何处理物理内存和虚拟内存的 物理内存管理&#xff1a; 虚拟内存管理&#xff1a; Linux是如何处理物理内存和虚拟内存的 物理内存管理&#xff1a; …

osg qt5.15 osg3.6.3 osgEarth3.1 编译爬山

Demo演示&#xff1a;Qt5.15.2OSG3.6.3OsgEarth3.1的QtCreator下的msvc2019x64版本 osgQt编译 步骤一&#xff1a;下载解压 步骤二&#xff1a;CMake配置 步骤三&#xff1a;CMake配置添加osg环境 步骤四&#xff1a;CMake配置添加Qt环境 步骤五&#xff1a;CMake修改CMakeLis…