(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 等脚本语言中流行起来。

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

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

varV: Variant;

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

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

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

varV: Variant;S: string;
beginV := 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和变体的两个非常相似的循环中的第一个:

constMaxNo = 10_000_000; // 1000万
varTime1, Time2: TDateTime;N1, N2: Variant;
beginTime1 := Now;N1 := 0;N2 := 0;while N1 < MaxNo dobeginInc(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.mzph.cn/news/699074.shtml

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

相关文章

高刷电竞显示器 - HKC VG253KM

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

Python实战:统计字符串中的英文字母、空格、数字及其他字符出现的个数

Python实战&#xff1a;统计字符串中的英文字母、空格、数字及其他字符出现的个数 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程 &…

JAVA面试题23

什么是Java中的字符串常量池&#xff08;String Pool&#xff09;&#xff1f; 答案&#xff1a;字符串常量池是Java中存储字符串常量的特殊区域&#xff0c;它位于堆内存中。由于字符串的不变性&#xff0c;相同的字符串常量在常量池中只会有一份拷贝。 什么是内部类&#xf…

个人博客系统测试

文章目录 一、项目介绍二、测试1. 功能测试2. 自动化测试&#xff08;1&#xff09;添加相关依赖&#xff08;2&#xff09;新建包并在报下创建测试类&#xff08;3&#xff09;亮点及难点 一、项目介绍 个人博客系统采用前后端分离的方法来实现&#xff0c;同时使用了数据库来…

windows11本地深度学习环境搭建Anacond,keras,tensorflow,pytorch, jupyter notebook

前言 工欲善其事&#xff0c;必先利其器。 第一步 安装Anaconda 下载地址&#xff1a; https://www.anaconda.com/download 路径默认 这里都勾选上 然后会卡在这里&#xff0c;卡很久&#xff0c;不用管&#xff0c;等着就行 第二步 配置环境 conda env list 列出所有…

Redis可视化工具——RedisInsight

文章目录 1. 下载2. 安装3. RedisInsight 添加 Redis 数据库4. RedisInsight 使用 RedisInsight 是 Redis 官方出品的可视化管理工具&#xff0c;支持 String、Hash、Set、List、JSON 等多种数据类型的管理&#xff0c;同时集成了 RedisCli&#xff0c;可进行终端交互。 1. 下载…

电子器件系列63:焊带(光伏焊带)

光伏焊带&#xff0c;又称涂锡焊带。光伏焊带是光伏组件的重要组成部分&#xff0c;属于电气连接部件&#xff0c;应用于光伏电池片的串联或并联&#xff0c;发挥导电聚电的重要作用&#xff0c;以提升光伏组件的输出电压和功率。光伏焊带是光伏组件焊接过程中的重要材料&#…

ShardingSphere 5.x 系列【15】分布式主键生成器

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.1.0 本系列ShardingSphere 版本 5.4.0 源码地址:https://gitee.com/pearl-organization/study-sharding-sphere-demo 文章目录 1. 概述2. 配置3. 内置算法3.1 UUID3.2 Snowflake3.3 NanoId3.4 CosId3.5 Co…

美客多如何批量注册买家账号?

美客多在南美电商领域可是个大佬。它的实力强大&#xff0c;影响力广泛&#xff0c;被大家尊称为南美电商巨头。它的业务范围覆盖了整个拉丁美洲&#xff0c;特别是一些重要的国家&#xff0c;比如墨西哥、阿根廷、玻利维亚、巴西、智利和哥伦比亚&#xff0c;这些地方都有它的…

虚拟化安全知识全攻略:保障云端数据安全

通过虚拟化技术使不同用户的数据可以存储在物理存储上。这种方式不但可以节约存储空间&#xff0c;还可以进行统一管理&#xff0c;降低管理费用。随着虚拟化技术的大规模使用&#xff0c;组织机构数据中心的基础架构、运维管理等都发生重大变化&#xff0c;面临的安全风险也随…

【开源】SpringBoot框架开发婚恋交友网站

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 会员管理模块2.3 新闻管理模块2.4 相亲大会管理模块2.5 留言管理模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 会员信息表3.2.2 新闻表3.2.3 相亲大会表3.2.4 留言表 四、系统展示五、核心代码5.…

redis配置和使用

安装redis sudo apt install redis-server查看redis版本 redis-server --version修改配置 sudo vim /etc/redis/redis.conf建议使用末行模式的匹配功能单词前加上&#xff1f;即可 bind 127.0.0.1注释掉daemonize属性改为yesprotected-mode属性改为 no 关闭保护模式require…

cookie伪造 [BSidesCF 2019]Kookie1

打开题目 提示用admin用户登录 尝试弱口令发现&#xff0c;登录失败 显示用admin&passwordadmin!进行登录 有发现说cookie&#xff0c;就尝试用cookie登录&#xff1a; f12编辑添加cookie重发包: 或者bp抓包 Cookie:usernameadmin 用admin登录成功 得到flag: 参考文章&…

Nmap详解

Nmap(Network Mapper,网络映射器)是一款开放源代码的网络探测和安 全审核工具。它被设计用来快速扫描大型网络&#xff0c;包括主机探测与发现、开放的端口情 况、操作系统与应用服务指纹识别、WAF 识别及常见安全漏洞。它的图形化界面是 Zenmap, 分布式框架为DNmap。 Nm…

TensorFlow2.x 精选笔记(1)数据基本操作与线性代数

学习参考&#xff1a; 动手学深度学习2.0Deep-Learning-with-TensorFlow-bookpytorchlightning 一、数组与张量 虽然张量看起来是复杂的对象&#xff0c;但它们可以理解为向量和矩阵的集合。理解向量和矩阵对于理解张量至关重要。 向量是元素的一维列表&#xff0c;向量是一…

C++的vector容器->基本概念、构造函数、赋值操作、容量和大小、插入和删除、数据存取、互换容器、预留空间

#include<iostream> using namespace std; #include <vector> //vector容器构造 void printVector(vector<int>& v) { for (vector<int>::iterator it v.begin(); it ! v.end(); it) { cout << *it << " "…

【人脸朝向识别与分类预测】基于LVQ神经网络

课题名称&#xff1a;基于LVQ神经网络的人脸朝向识别分类 版本日期&#xff1a;2024-02-20 运行方式&#xff1a;直接运行GRNN0503.m文件 代码获取方式&#xff1a;私信博主或 企鹅号:491052175 模型描述&#xff1a; 采集到一组人脸朝向不同角度时的图像&#xff0c;图像…

Python urllib、requests、HTMLParser

HTTP协议 HTTP 协议&#xff1a;一般指HTTP(超文本传输)协议。 HTTP是为Web浏览器和Web服务器之间的通信而设计的&#xff0c;基于TCP/IP通信协议嘞传递数据。 HTTP消息结构 客户端请求消息 客户端发送一个HTTP请求到服务器的请求消息包括以下格式 请求行(request line)请求…

spark超大数据批量写入redis

利用spark的分布式优势&#xff0c;一次性批量将7000多万的数据写入到redis中。 # 配置spark接口 import os import findspark from pyspark import SparkConf from pyspark.sql import SparkSession os.environ["JAVA_HOME"] "/usr/local/jdk1.8.0_192"…

C语言中的大小写字母转换

引言 在C语言编程中&#xff0c;我们经常需要进行大小写字母的转换。在 ASCII 码中&#xff0c;大写字母和小写字母之间的差值是固定的&#xff0c;因此我们可以利用这一特性进行大小写转换。本文将详细介绍C语言中大小写字母转换的具体步骤。 大小写转换的原理 在ASCII码表…