当前位置: 首页 > news >正文

(delphi11最新学习资料) Object Pascal 学习笔记---第6章第3节(传递字符串作为参数)

6.3 字符串数据类型

Object Pascal 中的字符串数据类型比简单的字符数组复杂得多,其功能远远超出了大多数编程语言为类似数据类型提供的功能。在本节中,我将介绍这种数据类型背后的关键概念;在接下来的章节中,我们将更详细地探讨其中的一些特性。

​ 在以下要点中,我总结了理解语言中字符串工作原理的关键概念(请记住,即使不了解这些概念,您也可以使用字符串,因为字符串的内部行为是非常透明的):

  • 字符串类型的数据在堆上动态分配。字符串变量只是对实际数据的引用。不必过多担心这一点,因为编译器会透明处理这个问题。与动态数组一样,当声明新字符串时,该字符串是空的。
  • 尽管可以以多种方式向字符串分配数据,但还可以通过调用SetLength函数来分配特定数量的内存。参数是字符串应该能够容纳的字符数(每个2字节)。扩展字符串时,现有数据将被保留(但可能会被移动到新的物理内存位置)。而缩小字符串时,部分内容可能会丢失。很少有必要设置字符串的长度。唯一常见的情况是需要将字符串缓冲区传递给指定平台的操作系统函数。。
  • 如果要增加字符串在内存中的大小(通过与另一个字符串连接),但相邻内存中有其他内容,则字符串不能在相同的内存位置中增长,因此必须在另一个位置制作字符串的完整副本。
  • 要清除字符串,不要对引用本身进行操作,只需将其设置为空字符串,即’ ',或者可以使用相对应的Empty常量。
  • 根据Object Pascal的规则,字符串的长度(可以通过调用Length获得)是有效元素的数量,而不是分配的元素的数量。与C不同,C具有字符串终止符(#0)的概念,从早期开始,所有版本的 Pascal 都倾向于使用特定的内存区域(字符串的一部分)来存储实际的长度信息。不过,有时你会发现字符串也有结束符。
  • Object Pascal 字符串使用引用计数机制,该机制会记录有多少个字符串变量在内存中引用给定的字符串。当字符串不再被使用时,即不再有字符串变量引用数据且引用计数为零时,引用计数将释放内存。
  • 字符串使用写时复制技术,非常高效。当将字符串赋值给另一个字符串或将其传递给例程的字符串参数时,不会复制数据,并且引用计数会增加。但是,如果更改其中一个引用的内容,系统将首先制作副本,然后仅修改该副本,其他引用保持不变。
  • 使用字符串连接向现有字符串添加内容的速度通常非常快,而且没有明显的缺点。虽然还有其他方法,但字符串连接既快速又强大。这在当今许多编程语言中并非如此。

​ 我想这样的描述可能会让人有点困惑,所以让我们来看看字符串在实际中的使用。稍后,我将通过一个演示来展示上述的一些操作,包括引用计数和写时复制。不过,在此之前,让我先回到字符串辅助操作和其他一些管理字符串的基本 RTL 函数上来。

​ 首先,让我们根据实际代码测验一下前面列表中的结论。由于字符串操作非常完美,除非您开始查看字符串的内存结构(在本书的较晚部分我会这样做,因为这在目前的阶段过于高级),否则很难完全理解发生了什么。因此,让我们从 Strings101 示例中提取的一些简单字符串操作开始:

varString1, String2: string;
beginString1 := 'Hello world';String2 := String1;Show('1: ' + String1);Show('2: ' + String2);String2 := String2 + ', again';Show('1: ' + String1);Show('2: ' + String2);
end;

当执行此第一个代码段时,如果将两个字符串赋值相同的内容,修改其中一个不会影响另一个。也就是说,String1不受对String2的更改的影响:

1: Hello world
2: Hello world
1: Hello world
2: Hello world, again

不过,在后面的演示中我们会更好地了解到,初始赋值并不会导致字符串的完全复制,复制是延迟的,这种特性被称为写时复制(copy-on-write)。

​ 另一个需要了解的重要特性是如何管理长度。如果询问字符串的长度,就会得到实际值(实际值存储在字符串元数据中,因此操作速度非常快)。但如果调用 SetLength,则需要分配内存,而内存通常不会被初始化。这通常用于将字符串作为缓冲区传递给外部系统函数。

​ 如果需要一个空字符串,可以使用伪构造函数Create。最后,您可以使用SetLength修剪字符串。以下代码演示了所有这些情况:

varString1: string;
beginString1 := 'Hello world';Show(String1);Show('Length: ' + String1.Length.ToString);SetLength(String1, 100);Show(String1);Show('Length: ' + String1.Length.ToString);String1 := 'Hello world';Show(String1);Show('Length: ' + String1.Length.ToString);String1 := String1 + string.Create(' ', 100);SetLength(String1, 100);Show(String1);Show('Length: ' + String1.Length.ToString);
end;

输出大致如下:

Hello world
Length: 11
֐~ֳ~ו~׵~؛~ف~٦~ڋ~گ~ۓ~~Helloworld~̆~~̫ ͌~ʹ~Η~υ~ϧ~Ј~Щ~ы~ѭ~ҏ~ұ~Ә~Ӽ~ԟ~Շ~հ
~〈~⌇~۵~ܚ~ܼ~ݡ~~ރ~ޤ~ߊ~߰~֐~֐~֐~֐~ࢮ~ ~֐~ Length: 100
Hello world
Length: 11
Hello world
Length: 100

​ 节要强调的第三个概念是空字符串。当字符串的内容是空字符串时,它就是空字符串。无论是赋值还是测试,都可以使用两个连续的引号或特定函数:

varString1: string;
beginString1 := 'Hello world';if String1 = '' thenShow('Empty')elseShow('Not empty');String1 := ''; // 或者 String1.Empty;if String1.IsEmpty thenShow('Empty')elseShow('Not empty');
end;

上述代码生成这个简单的输出:

Not empty
Empty
6.3.1 传递字符串作为参数

​ 正如我已经解释过的,如果你将一个字符串赋值给另一个字符串,你只是复制了一个引用,而内存中的实际字符串并没有被复制。但是,如果你编写的代码改变了该字符串,那么字符串就会首先被复制(仅在该点),然后被修改。

​ 将字符串作为参数传递给函数或过程时,也会发生类似的情况。默认情况下,你会获得一个新的引用,如果你在函数中修改了字符串,这并不会影响原始字符串。如果想获得不同的行为,即在函数中修改原始字符串,则需要使用 var 关键字通过引用传递字符串(就像大多数其他简单数据类型和托管数据类型一样)。

​ 但如果不想修改作为参数传递的字符串呢?在这种情况下,可以对参数使用 const 修饰符进行优化。这样做意味着编译器不会让你在函数或过程中修改字符串,但也会因此优化参数传递操作。事实上,const 字符串不需要函数在开始时增加字符串引用计数,也不需要在结束时减少字符串引用计数,因为函数知道字符串不能被修改。

​ 虽然字符串管理的例程非常快,但执行数千或数百万次也会给程序增加一点开销。这就是为什么在函数不需要修改字符串参数值的情况下,建议将字符串作为常量传递(尽管下面的注释中提到了潜在存在的问题)。

​ 用编码术语来说,这是三个以不同方式传递字符串参数的过程的声明:

procedure ShowMsg1(Str: string);
procedure ShowMsg2(var Str: string);
procedure ShowMsg3(const Str: string);

注解:近年来,除非函数和方法需要对字符串进行修改,否则强烈所有字符串参数都应作为常量传递。但有一个非常重要的注意事项:对于常量字符串参数,编译器获取字符串引用后不会对其进行 “管理”(不进行引用计数等),而是将其视为指向内存位置的指针。编译器会正确检查例程的代码是否不会更改字符串参数。但是,编译器无法控制参数所指向的原始字符串会发生什么变化。

​ 对该字符串的更改会影响其内存布局和位置,这一点普通字符串参数可以处理(具有多个引用的字符串会自动执行写时复制操作),而常量字符串参数则会受到这些更改的影响。换句话说,对原始字符串的更改会使引用它的常量参数失效,使用它很可能会导致内存访问错误。

相关文章:

(delphi11最新学习资料) Object Pascal 学习笔记---第6章第3节(传递字符串作为参数)

6.3 字符串数据类型 ​ Object Pascal 中的字符串数据类型比简单的字符数组复杂得多,其功能远远超出了大多数编程语言为类似数据类型提供的功能。在本节中,我将介绍这种数据类型背后的关键概念;在接下来的章节中,我们将更详细地探…...

k8s节点负载使用情况分析命令kubectl describe node [node-name]

1.到任意安装了kubectl节点命令的节点上执行kubectl describe node [node-name] 上面的Requests最小分配 Limits最大分配是所有pod之和,最小分配之和不能超过服务器实际参数,否则新的pod会因为资源不够起不来,最大分配是预设之和&#xff0…...

自动驾驶加速落地,激光雷达放量可期(上)

1 激光雷达应用广泛,汽车有望成最大催化 激光雷达(LiDAR)是一种主动遥感技术,通过测定传感器发出的激光在传感器与目标物体之间的传播距离,来分析目标地物表面的反射能量大小、反射波谱的幅度、频率和相位等信息&#…...

变量的间接引用

场景: 如果第一个变量的值是第二个变量的名字,我们能够从第一个变量中取得第二个变量的值吗?例如,如果aztj且ztjz,那么我们能够通过引用变量a来获得值z吗?答案是可以,它被称为间接引用&#xf…...

学习JAVA的第六天(基础)

目录 集合 集合和数组的对比 ArrayList成员方法 ArrayList成员方法代码展示 练习 集合的遍历01之字符串 集合的遍历02之数字 集合的遍历03之学生对象 集合 集合和数组的对比 从长度维度来看 数组长度固定 集合长度可变从存储类型维度来看 数组可以存放基本数据类型和…...

LeetCode 2673.使二叉树所有路径值相等的最小代价:自顶向下的DFS 或 自底向上的递推

【LetMeFly】2673.使二叉树所有路径值相等的最小代价:自顶向下的DFS 或 自底向上的递推 力扣题目链接:https://leetcode.cn/problems/make-costs-of-paths-equal-in-a-binary-tree/ 给你一个整数 n 表示一棵 满二叉树 里面节点的数目,节点编…...

9、电源管理入门之CPU Idle

目录 1. CPU Idle有什么用? 2. CPU Idle整体框架 3. Idle状态判断 3. cpuidle core 4. 注册初始化 4.1 cpuidle governor注册 4.2 cpuidle driver注册 4.3 cpuidle device注册 5. cpuidle触发流程 关于Linux的很多知识其实网上的资料非常的多,但是也有些问题: 有时…...

uniapp的扩展组件uni-popup 弹出层自动打开

我的需求是在页面加载完之后自动打开弹窗,自动打开只能写在onReady 或 mounted 生命周期内,这是这个组件的规定: 如果想在页面渲染完毕后就打开 uni-popup ,请在 onReady 或 mounted 生命周期内调用,确保组件渲染完毕…...

二、mysql常用函数

目录 一、Mysql数值型函数 二、Mysql字符串函数 三、Mysql日期和时间函数 四、Mysql聚合函数 五、Mysql流程控制函数 六、其他函数 一、Mysql数值型函数 函数名称 作用 abc 求绝对值 sqrt 求二次方根 mod 求余数 ceil 和 ceiling 功能一样,都是返回不小…...

【Redis | 第一篇】快速了解Redis

文章目录 1.快速了解Redis1.1简介1.2与其他key-value存储的不同处1.3Redis安装——Windows环境1.3.1下载redis1.3.2启动redis1.3.3进入redis客户端1.3.4修改配置 1.4Redis安装——Linux环境1.4.1安装命令1.4.2启动redis1.4.3进入redis客户端 1.5配置修改1.6小结 1.快速了解Redi…...

Vim 模式切换 | 命令集

Vim 模式切换 | 命令集 vim 主要模式及切换一、正常/普通/命令模式1 光标相关操作命令集1.1 光标移动1.2 文字删除1.3 粘贴和复制1.4 撤销1.5 字符更改 二、插入模式2.1 插入模式和命令行模式相互切换 三、末行模式2.1 末行模式和命令行模式相互切换2.2 末行模式相关命令集 四、…...

广和通5G智能模组SC171支持Android、Linux和Windows系统,拓宽智能物联网应用

世界移动通信大会2024期间,广和通宣布:5G智能模组SC171除支持Android操作系统外,还兼容Linux和Windows系统,帮助更多智能终端客户快速迭代产品,拓宽智能化应用覆盖范围。 广和通SC171系列基于高通QCM6490物联网解决方案…...

【51单片机】红外遥控红外遥控电机调速(江科大)

1.红外遥控简介 红外遥控是利用红外光进行通信的设备,由红外LED将调制后的信号发出,由专用的红外接收头进行解调输出 通信方式:单工,异步 红外LED波长:940nm 通信协议标准:NEC标准 2.硬件电路 红外发送部分 IN高电平时,LED不亮,IN低电平时&…...

kubesphere jenkins 流水线 未运行(解决方案)

场景: 在kubesphere 中运行 流水线 devops 结果,显示未运行 但是用 admin 账户是可以运行成功的。 问题解决 1- 查日志: 然后 Caused: org.acegisecurity.userdetails.UsernameNotFoundException: org.springframework.security.core.…...

如何保护服务器的安全

互联网的迅速发展,让很多企业都很重视网络技术的使用,但是网络的传播速度比较快,同时容易造成数据、隐私方面的泄露现在每个企业基本有自己的服务器。有几点需要注意,可以参考: 1.基础密码安全 最基本的安全就是密码安…...

Python使用HDL 模拟器实现 FPGA 板卡的仿真验证

Python 结合 HDL 模拟器实现 FPGA 板卡的仿真验证,您可以借助一些开源工具和库来实现这一目的。下面我将为您介绍一种常用的方法,使用 Python 结合 Verilog 模拟器和 FPGA 开发工具进行仿真验证。 ### 步骤概述 1. **编写 Verilog 设计**:首…...

vue中 input disable后无法触发点击事件

问题:input标签为disabled后,点击事项无效;当点击文字**“请选择”**时无法触发点击事件,其父标签的其余位置均可触发 解决:只需要在input标签中添加 style“pointer-events:none” 即可 pointer-events: none 作用是…...

实战一个 Jenkins 构建 CI/CD流水线 的简单配置过程哈

引言:上一期我们讲述了gitlabCI/CD工具的介绍,工具之争,本期我们介绍Jenkins CI/CD 目录 一、Jenkins介绍 1、Jenkins概念 2、Jenkins目的 3、特性 4、产品发布流程 二、安装Jenkins 1、安装JDK 2、安装Jenkins 1、上传压缩包 2、…...

【InternLM 实战营笔记】大模型评测

随着人工智能技术的快速发展, 大规模预训练自然语言模型成为了研究热点和关注焦点。OpenAI于2018年提出了第一代GPT模型,开辟了自然语言模型生成式预训练的路线。沿着这条路线,随后又陆续发布了GPT-2和GPT-3模型。与此同时,谷歌也…...

数据卷(Data Volumes) 自定义镜像(dockerfile)

目录 一. 数据卷(Data Volumes) 1.1 什么是数据卷 1.2 为什么需要数据卷 1.3 数据卷的作用 1.4 数据卷的使用 二. 自定义镜像(dockerfile) 2.1 什么是dockerfile 2.2 自定义centos 2.3 自定义tomcat 一. 数据卷(Data…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...