(delphi11最新学习资料) Object Pascal 学习笔记---第5章第4节( 变体类型 )

5.4 变体类型(Variant)

​ 最初,Obejct Pascal为了提供完整的Windows OLECOM支持,引入了一种松散的本地数据类型,称为变体(variant)。 虽然这个名称让人联想到变体记录(前面提到过)并且实现方式与开放式数组形参有些相似,但变体是一种独立的语言特性,有非常特殊的实现方式(在Windows开发之外的语言中不太常见)。

​ 在本节中,我不会真正提及 OLE 或使用这种数据类型的其他情况(如数据集的字段访问),我只想从一般角度讨论这种数据类型。

​ 在第 16 章中,我将重新讨论动态类型、RTTI 和反射,并将介绍一种相关的(但类型安全且速度更快)RTL 数据类型,即 TValue。

5.4.1 变体没有类型

​ 通常,您可以使用变体类型的变量存储任何基本数据类型并执行许多操作和类型转换。自动类型转换违反了Object Pascal语言的一般类型安全方法,是一种动态类型的实现,最初由 Smalltalk 和 Objective-C 等语言引入,最近在 JavaScript、PHP、Python 和 Ruby 等脚本语言中流行起来。

​ 变体在运行时进行类型检查和计算。编译器不会警告在代码中可能存在的错误,只有通过大量测试才能发现这些错误。总的来说,你可以将使用变体的代码部分视为解释型代码,因为与解释型代码一样,许多操作要到运行时才能解析,这会影响代码的运行速度。

​ 既然我已经警告过你不要使用变体类型,那么现在是时候看看你能用它做些什么了。基本上,一旦你声明了一个变量,比如下面这样的变量:

var
  V: Variant;

您可以将多种不同类型的值赋给它:

V := 10;
V := 'Hello, World';
V := 45.55;

​ 一旦有了变体值,您可以将其复制到任何数据类型中,无论兼容或不兼容。如果将值赋值给不兼容的数据类型,编译器通常也不会生成错误,而是在运行时进行转换(如果有意义的话)。否则,它会报出运行时错误。从技术上讲,变体存储类型信息以及实际数据,允许进行一些方便但缓慢且不安全的运行时操作。 考虑以下代码(VariantTest示例的一部分),它是上面代码的扩展:

var
  V: Variant;
  S: string;
begin
  V := 10;
  S := V;
  V := V + S;
  Show(V);
  V := 'Hello, World';
  V := V + S;
  Show(V);
  V := 45.55;
  V := V + S;
  Show(V);

很有趣,不是吗?毫不奇怪,输出如下:

20
Hello, World10
55.55

​ 除了将包含字符串的变体赋值给变量S之外,还可以将整数或浮点数的变体赋值给变体。更糟糕的是,您可以使用变体来计算值,比如V := V + S 这个操作根据变体中存储的数据以不同的方式解释。在上面的代码中,同一行可以添加整数、浮点值或连接字符串。

​ 至少可以说,编写涉及变量的表达式是有风险的。如果字符串包含一个数字,则一切正常。如果不包含,则会出现异常。如果没有令人信服的理由,就不应该使用变量类型,而应该坚持使用标准的 Object Pascal 数据类型和类型检查方法。

5.4.2 深入了解变体

​ 对于那些有兴趣了解变体更多细节的人,请允许我补充一些技术信息,介绍变体的工作原理以及如何对其进行更多控制。RTL 包含一种变体记录类型 TVarData,其内存布局与变体类型相同。您可以用它来访问变体的实际类型。TVarData 结构包括变体类型(以 VType 表示)、一些保留字段和实际值。请注意,有空值的概念,可以使用NULL(而不是nil)进行赋值。

注解:有关更多详细信息,请查看RTL源代码中System单元中的TVarData定义。这远非是一个简单的结构,我建议只有一些经验的开发人员才去了解变体类型的实现细节。

​ VType 字段的可能值与 OLE 自动化中可以使用的数据类型相对应,这些数据类型通常被称为 OLE 类型或变量类型。下面是按字母顺序排列的可用变量类型的完整列表:

varAny         varArray        varBoolean       varByte
varByRef       varCurrency     varDate          varDispatch
varDouble      varEmpty        varError         varInt64
varInteger     varLongWord     varNull          varOleStr
varRecord      varShortInt     varSingle        varSmallint
varUString     varTypeMask     varUInt64        varUnknown
varUString     varVariant      varWord

​ 大多数这些变体类型的常量名易于理解。

​ 还有许多对变量进行操作的函数,可以用来进行特定的类型转换或查询变量类型的相关信息(例如 VarType 函数)。实际上,在编写使用变体的表达式时,大多数类型转换和赋值函数都会被自动调用。其他变体支持例程实际上是对变体数组进行操作,而变体数组也是一种几乎只用于 Windows 上 OLE 集成的结构。

5.4.3 变体很慢

​ 使用变体类型的代码很慢,不仅在转换数据类型时,甚至在只是将包含整数的两个变体值相加时也很慢。它们几乎与解释代码一样慢。要比较基于变体的算法与基于整数的相同代码的速度,您可以查看VariantTest项目的第二个按钮执行的代码。

​ 该程序运行一个循环,计时其速度,并在进度条中显示状态。以下是基于Int64和变体的两个非常相似的循环中的第一个:

const
  MaxNo = 10_000_000; // 1000万
var
  Time1, Time2: TDateTime;
  N1, N2: Variant;
begin
  Time1 := Now;
  N1 := 0;
  N2 := 0;
  while N1 < MaxNo do
  begin
    Inc(N2, N1);
    Inc(N1);
  end;
  // 我们必须使用结果
  Time2 := Now;
  Show(N2);
  Show('Variants: ' + FormatDateTime('ss.zzz', Time2 - Time1) + ' seconds');

​ 定时代码值得一看,因为它可以很容易地适配于任何类型的性能测试。如您所见,程序使用 Now 函数获取当前时间,并使用 FormatDateTime 函数输出时间差,只显示秒(“ss”)和毫秒(“zzz”)。在这个示例中,速度差实际上非常大,即使没有精确计时,你也能注意到。这些是我在 Windows 虚拟机上获得的数据:

49999995000000
Variants: 01.169 seconds
49999995000000
Integers: 00.026 second

​ 在我的虚拟机上,变体代码要慢50倍左右!实际值取决于您在哪个设备上运行此程序,但相对差异不会有太大变化。即使在我的Android手机上,我得到了类似的比例(但总体时间更长):

49999995000000
Variants: 07.717 seconds
49999995000000
Integers: 00.157 second

​ 在我的手机上,这段代码花费的时间是在Windows上的6倍多,但事实上,两者之间的净差异超过7秒,使得基于变体的实现对用户而言明显较慢,而基于Int64的实现仍然非常快(用户几乎不会注意到十分之一秒)。

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

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

相关文章

GPT-SoVITS 快速声音克隆使用案例:webui、api接口

参考: https://github.com/RVC-Boss/GPT-SoVITS 环境: Python 3.10 PyTorch 2.1.2, CUDA 12.0 安装包: 1、使用: 1)下载项目 git clone https://github.com/RVC-Boss/GPT-SoVITS.git2)下载预训练模型 https://huggingface.co/lj1995/GPT-SoVITS 下载模型文件放到GPT…

高刷电竞显示器 - HKC VG253KM

今天给大家分享一款高刷电竞显示器 - HKC VG253KM。 高刷电竞显示器 - HKC VG253KM源于雄鹰展翅翱翔的设计灵感&#xff0c;严格遵循黄金分割比例的蓝色点晴线条&#xff0c;加上雾面工艺及高低起伏错落有致的线条处理&#xff0c;在VG253KM的背部勾勒出宛若大鹏展翅的鹰翼图腾…

关于Kinect 互动沙盘 深度图 Shader Graph 分层

把Kinect的深度图穿给Shader Graph using com.rfilkov.kinect; using UnityEngine; using UnityEngine.UI; public class GetDepthTex : MonoBehaviour { public Material Mat_SandTable; void Update() { Mat_SandTable.SetTexture("_MainTex"…

网络安全笔记总结

IAE引擎 1.深度检测技术--DFI和DPI技术 DFI和DPI都是流量解析技术&#xff0c;对业务的应用、行为及具体信息进行识别&#xff0c;主要应用于流量分析及流量检测。 DPI&#xff1a;深度包检测技术 DPI是一种基于应用层的流量检测和控制技术&#xff0c;对流量进行拆包&#x…

关于git子模块实践(一)

背景 在日常项目开发中&#xff0c;随着项目的迭代&#xff0c;不可避免的是主项目会引入到很多三方库&#xff0c;或者自研的一些模块。有一种场景&#xff0c;就是这些模块&#xff0c;是随着开发而进行迭代&#xff0c;且多个项目公用的&#xff0c;这种情况&#xff0c;在…

测试开源C#人脸识别模块DlibDotNet

百度“C# 换脸”找到参考文献4&#xff0c;发现其中使用DlibDotNet检测并识别人脸&#xff08;之前主要用的是ViewFaceCore&#xff09;&#xff0c;DlibDotNet是Dlib的.net封装版本&#xff0c;后者为开源C工具包&#xff0c;支持机器学习算法、图像处理等算法以支撑各类高级应…

袁庭新ES系列09节 | 使⽤kibana对类型及映射操作

前言 类型及映射是Elasticsearch中重要的两个概念。本章节袁老师将带领同学们来学习Elasticsearch中的类型和映射部分的内容。先透露一下&#xff0c;在Elasticsearch中&#xff0c;类型&#xff08;type&#xff09;相当于关系数据库中的table概念&#xff1b;映射&#xff0…

微服务三十五关

1.微服务有什么好处&#xff1f; 微服务优点很多&#xff0c;但是我们通常说一个东西好肯定会跟另一个东西比较&#xff0c; 通常说微服务好会和单体项目进行比较。以下是微服务相对于单体项目的一些显著好处&#xff1a; 首先&#xff0c;让我们讨论单体项目的一些主要缺点&a…

解决ubuntu系统cannot find -lc++abi: No such file or directory

随着CentOS的没落&#xff0c;使用ubuntu的越来越多&#xff0c;而且国外貌似也比较流行使用ubuntu&#xff0c;像LLVM/Clang就有专门针对ubuntu编译二进制发布文件&#xff1a; ubuntu本身也可以直接通过apt install命令来安装编译好的clang编译器。不过目前22.04版本下最高…

高通 Android 12 Settings不显示版本号问题

1、最近项目遇到一个奇葩问题&#xff0c;编译系统版本号不见了&#xff1f; 2、一开始我想着可能是自己代码没有make clean结果编译几个小时&#xff0c;然后烧录固件发现还是未生效。 3、然后这时候我又去看git log review最近修改也没有太大发现&#xff08;待定&#xff…

第10章 高级缓存一致性设计

缓存一致性协议如何适应更大规模的系统。广播和侦听协议更早地涉及了可扩展性问题&#xff0c;因为流量和侦听频率时随着处理器个数的增加至少呈线性增加趋势&#xff0c;可用的互连网络带宽会很快被广播流量占满。本章讨论的基于目录式缓存一致性协议来实现可扩展性。主要问题…

ApexRBp在线粒子传感器在电动汽车电池制造的应用

电动汽车电池的崛起与颗粒污染的挑战 随着电动汽车&#xff08;EV&#xff09;市场的迅速扩张&#xff0c;对高性能锂离子电池的需求也急剧增加。这些电池不仅是EV的心脏&#xff0c;更是推动其前行的核心动力。然而&#xff0c;在电池制造的每一个环节&#xff0c;都需要对多…

86、移除推理路径上的所有内存操作

动态申请内存的影响,前两节已经介绍过了,细心的朋友可能会发现,在使用 C++实现的 resnet50 代码中,还存在一处动态申请内存的操作。 那就是对于每一层的输入或输出 feature map 数据进行内存申请,比如在 3rd_preload/ops/conv2d.cc 文件中,卷积的计算中存在对于输出 fea…

转运机器人,AGV底盘小车:打造高效、精准的汽车电子生产线

为了满足日益增长的市场需求&#xff0c;保持行业领先地位&#xff0c;某汽车行业电子产品企业引入富唯智能AMR智能搬运机器人及其智能物流解决方案&#xff0c;采用自动化运输措施优化生产节拍和搬运效率&#xff0c;企业生产效率得到显著提升。 项目背景&#xff1a; 1、工厂…

python 提取PDF文字

使用pdfplumber&#xff0c;不能提取扫描的pdf和插入的图片。 import pdfplumberfile_path rD:\UserData\admindesktop\官方文档\1903_Mesh-Models-Overview_FINAL.pdf with pdfplumber.open(file_path) as pdf:page pdf.pages[0]print(page.extract_text()) # 所以文字prin…

零样本带解释性的医学大模型

带解释性的医学大模型 提出背景解法拆解方法的原因对比以前解法 零样本带解释性的医学大模型如何使用CLIP模型和ChatGPT来进行零样本医学图像分类用特定提示查询ChatGPT所生成的医学视觉特征描述相似性得分在不同症状上的可视化&#xff0c;用于解释模型的预测注意力图的可视化…

小世界网络:直径、分形、同配性

1.小世界网络特点 —— 网络直径接近于网络中节点数量的自然对数 2.小世界分形网络 —— 移除弱链接的小世界网络 3.同配性分析 —— Pearson相关系数、邻居相关度 在宏观层面上&#xff0c;关注平均度、度分布和聚类等全局结构特征的影响。更高的平均度被认为会导致更…

C#最优队列最小堆小顶堆大顶堆小根堆大根堆PriorityQueue的使用

最优队列有多种叫法&#xff0c;什么小根堆&#xff0c;大根堆&#xff0c;小顶堆&#xff0c;大顶堆。 队列分多种&#xff0c;线性队列&#xff08;简单队列&#xff09;&#xff0c;循环队列&#xff0c;最优队列等等。 最优队列&#xff0c;可以看作堆叠箱子&#xff0c;…

【JavaEE】_tomcat的安装与使用

目录 1. Tomcat简介 2. Tomcat安装 2.1 下载Tomcat并解压缩 2.2 启动Tomcat 2.2.1 Tomcat乱码问题 2.2.2 Tomcat闪退问题 2.3 访问Tomcat欢迎页面 3. 使用Tomcat部署前端代码 3.1 路径匹配 3.2 文件路径访问与网络访问 4. 静态页面与动态页面 5. 基于tomcat的网站后…

QEMU开发入门

1. 简介 QEMU&#xff08;Quick EMUlator&#xff09;是一个开源的虚拟化软件&#xff0c;它能够模拟多种硬件平台&#xff0c;并在这些平台上运行各种操作系统。QEMU可以在不同的主机架构之间进行虚拟化&#xff0c;例如x86、ARM、PowerPC、Risc-V等。QEMU是一个功能强大且灵…