(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会因为资源不够起不来,最大分配是预设之和࿰…...
自动驾驶加速落地,激光雷达放量可期(上)
1 激光雷达应用广泛,汽车有望成最大催化 激光雷达(LiDAR)是一种主动遥感技术,通过测定传感器发出的激光在传感器与目标物体之间的传播距离,来分析目标地物表面的反射能量大小、反射波谱的幅度、频率和相位等信息&#…...
变量的间接引用
场景: 如果第一个变量的值是第二个变量的名字,我们能够从第一个变量中取得第二个变量的值吗?例如,如果aztj且ztjz,那么我们能够通过引用变量a来获得值z吗?答案是可以,它被称为间接引用…...
学习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…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
