Delphi 的内存操作函数(2): 给数组指针分配内存
静态数组, 在声明时就分配好内存了, 譬如:
vararr1: array[0..255] of Char;arr2: array[0..255] of Integer; beginShowMessageFmt('数组大小分别是: %d、%d', [SizeOf(arr1), SizeOf(arr2)]);{数组大小分别是: 512、1024} end;
对静态数组指针, 虽然在声明之处并没有分配内存, 但这个指针应该分配多少内存是有定数的.
这种情况, 我们应该用 New 和 Dispose 来分配与释放内存. 譬如:
typeTArr1 = array[0..255] of Char;TArr2 = array[0..255] of Integer; vararr1: ^TArr1;arr2: ^TArr2; beginNew(arr1);New(arr2);arr1^ := '万一的 Delphi 博客';ShowMessageFmt('%s%s', [arr1^[0], arr1^[1]]); {万一} // ShowMessageFmt('%s%s', [arr1[0], arr1[1]]); {这样也可以}arr2[Low(arr2^)] := Low(Integer); {第一个元素赋最小值}arr2[High(arr2^)] := MaxInt; {第一个元素赋最大值}ShowMessageFmt('%d, %d', [arr2[0], arr2[255]]); {-2147483648, 2147483647}Dispose(arr1);Dispose(arr2); end;//变通一下, 再做一遍这个例子: typeTArr1 = array[0..255] of Char;TArr2 = array[0..255] of Integer;PArr1 = ^TArr1;PArr2 = ^TArr2; vararr1: PArr1;arr2: PArr2; beginNew(arr1);New(arr2);arr1^ := '万一的 Delphi 博客';ShowMessageFmt('%s%s', [arr1[0], arr1[1]]);arr2[Low(arr2^)] := Low(Integer);arr2[High(arr2^)] := MaxInt;ShowMessageFmt('%d, %d', [arr2[0], arr2[255]]); {-2147483648, 2147483647}Dispose(arr1);Dispose(arr2); end;
给已知大小的指针分配内存应该用 New, 上面的例子是关于静态数组指针的, 后面要提到的结构体(记录)的指针也是如此.
New 的本质也函数调用 GetMem, 但不需要我们指定大小了.
但这对动态数组就不合适了, 不过给动态数组分配内存 SetLength 应该足够了, 譬如:
vararr: array of Integer; beginSetLength(arr, 3);arr[0] := Random(100);arr[1] := Random(100);arr[2] := Random(100);ShowMessageFmt('%d,%d,%d', [arr[0],arr[1],arr[2]]); {0,3,86} end;
那怎么给动态数组的指针分配内存呢? 其实动态数组变量本身就是个指针, 就不要绕来绕去再给它弄指针了.
不过有一个理念还是满重要的, 那就是我们可以把一个无类型指针转换为动态数组类型, 譬如:
typeTArr = array of Integer; varp: Pointer; beginGetMem(p, 3 * SizeOf(Integer)); {分配能容纳 3 个 Integer 的空间}{这和 3 个元素的 TArr 的大小是一样的, 但使用时需要进行类型转换}TArr(p)[0] := Random(100);TArr(p)[1] := Random(100);TArr(p)[2] := Random(100);ShowMessageFmt('%d,%d,%d', [TArr(p)[0], TArr(p)[1], TArr(p)[2]]); {0,3,86}FreeMem(p); end;
这里用到了 GetMem 和 FreeMem, 对分配无类型指针这是比较常用的; 对其他类型的指针它可以, 但不见得是最好的方案, 譬如:
//获取窗口标题(显然不如用前面说过的 StrAlloc 更好) varp: Pointer; beginGetMem(p, 256);GetWindowText(Handle, p, 256);ShowMessage(PChar(p)); {Form1}FreeMem(p); end;
应该提倡用 GetMemory 和 FreeMemory 代替 GetMem、FreeMem, 譬如:
varp: Pointer; beginp := GetMemory(256);GetWindowText(Handle, p, 256);ShowMessage(PChar(p)); {Form1}FreeMemory(p); end;
先总结下:
New 是给已知大小的指针分配内存;
GetMem 主要是给无类型指针分配内存;
尽量使用 GetMemory 来代替 GetMem.
还有个 AllocMem 和它们又有什么区别呢?
AllocMem 分配内存后会同时初始化(为空), GetMem 则不会, 先验证下:
varp1,p2: Pointer; beginp1 := AllocMem(256);ShowMessage(PChar(p1)); {这里会显示为空}FreeMemory(p1);p2 := GetMemory(256);ShowMessage(PChar(p2)); {这里会显示一些垃圾数据, 内容取决与在分配以前该地址的内容}FreeMemory(p2); end;
关于 FreeMemory 与 FreeMem 的区别:
1、FreeMemory 会检查是否为 nil 再 FreeMem, 这有点类似: Free 与 Destroy;
2、FreeMem 还有个默认参数可以指定要释放的内存大小, 不指定就全部释放(没必要只释放一部分吧);
3、New 对应的 Dispose 也可以用 FreeMem 或 FreeMemory 代替.
尽量使用 FreeMemory 来释放 GetMem、GetMemory、AllocMem、ReallocMem、ReallocMemory 分配的内存.
ReallocMem、ReallocMemory 是在已分配的内存的基础上重新分配内存, 它俩差不多 ReallocMemory 比 ReallocMem 多一个 nil 判断, 尽量使用 ReallocMemory 吧. 譬如:
typeTArr = array[0..MaxListSize] of Char;PArr = ^TArr; vararr: PArr;i: Integer; beginarr := GetMemory(5);for i := 0 to 4 do arr[i] := Chr(65+i);ShowMessage(PChar(arr)); {ABCDE}arr := ReallocMemory(arr, 26);ShowMessage(PChar(arr)); {ABCDE}for i := 0 to 25 do arr[i] := Chr(65+i);ShowMessage(PChar(arr)); {ABCDEFGHIJKLMNOPQRSTUVWXYZ} end;
注意上面这个例子中 TArr 类型, 它被定义成一个足够大的数组; 这种数组留出了足够的可能性, 但一般不会全部用到.
我们一般只使用这种数组的指针, 否则一初始化将会内存不足而当机.
即便是使用其指针, 也不能用 New 一次行初始化; 应该用 GetMem、GetMemory、AllocMem、ReallocMem、ReallocMemory 等用多少申请多少.
需要注意的是, 重新分配内存也可能是越分越少; 如果越分越大应该可以保证以前数据的存在.
这在 VCL 中 TList 类用到的理念.
如果你在心里上接受不了那么大一个数组(其实没事, 一个指针才多大? 我们只使用其指针), 也可以这样:
typeTArr = array[0..0] of Char;PArr = ^TArr; vararr: PArr;i: Integer; beginarr := GetMemory(5);for i := 0 to 4 do arr[i] := Chr(65+i);ShowMessage(PChar(arr)); {ABCDE}arr := ReallocMemory(arr, 26);ShowMessage(PChar(arr)); {ABCDE}for i := 0 to 25 do arr[i] := Chr(65+i);ShowMessage(PChar(arr)); {ABCDEFGHIJKLMNOPQRSTUVWXYZ} end;
这好像又让人费解, 只有一个元素的数组能干什么?
应该这样理解: 仅仅这一个元素就足够指示数据的起始点和数据元素的大小和规律了.
另外的 SysGetMem、SysFreeMem、SysAllocMem、SysReallocMem 四个函数, 应该是上面这些函数的底层实现, 在使用 Delphi 默认内存管理器的情况下, 我们还是不要直接使用它们.
Delphi 的内存操作函数(2): 给数组指针分配内存相关推荐
- Delphi 的内存操作函数(1): 给字符指针分配内存
马上能想到的函数有: GetMem AllocMem ReallocMem FreeMemGetMemory ReallocMemory FreeMemoryNew DisposeNewStr Dis ...
- c语言指针如何增加内存大小,C语言如何给指针分配内存?
匿名用户 1级 2010-09-20 回答 看了下,基本上回答的都是用new 那个,都是C++程序员吧 c语言里面是用malloc的 写了个简单程序,看看是不是楼主需要的 #include #incl ...
- 【C 语言】二级指针作为输入 ( 自定义二级指针内存 | 为 二级指针 分配内存 - 存放 一维指针 | 为每个 一级指针 分配内存 | 释放二维指针内存 )
文章目录 一.二级指针 1.为 二维指针 分配内存 2.为每个 一维指针 分配内存 3.释放 二维指针 内存 二.完整代码示例 一.二级指针 声明二级指针 : // 声明二维指针char **p = ...
- C 中的内存操作函数-memcpy 等(to be continued)
文章目录 C中的内存操作函数 1.memcpy() 1.1 函数介绍 1.2 示例代码 1.3 Reference C中的内存操作函数 1.memcpy() 1.1 函数介绍 void *memcpy ...
- C语言——常见的字符串函数+内存操作函数的介绍及实现
文章目录 前言 一.字符串函数 1.求字符串长度 strlen 2.长度不受限制的字符串函数strcpy.strcat.strcmp 字符串拷贝 strcpy 字符串追加拷贝 strcat 字符串比较 ...
- C语言程序设计 | 模拟实现内存操作函数:strncpy, strncat, strncmp, memcpy, memmove
模拟实现字符串和内存操作函数(二)目录: strncpy strncat strncmp strcmp memcpy memmove strncpy char* strncpy(char* dst, ...
- 字符串转内存c语言,【一起学C】C语言面试题必考:字符串操作函数,内存操作函数实现...
本帖最后由 奉聪 于 2017-1-25 14:54 编辑 *******前言******* 我数一下,我发了几个帖子,1.2.3? 哈哈哈,没几个哈,感谢吾爱,让我学到了很多,乐于分享,共同进步! ...
- 【C进阶】之动态内存分配及内存操作函数
动态内存分配及内存操作函数 1 动态内存分配的介绍 2 malloc和free函数 3 测试代码 4 goto的使用场合,常用于出错处理 5 memset() 6 memcpy() 7 memcmp( ...
- C语言--内存操作函数memmove
文章目录 一.C语言--内存操作函数memmove 1.1 memmove函数介绍 1.2 memmove使用示例 二.模拟实现memmove函数 一.C语言–内存操作函数memmove 1.1 me ...
最新文章
- 解决git本地提交不到远程库
- 大佬教你修改pycharm编辑器 简单的四步教你搞定界面风格修改
- RabbitMQ学习总结(2)——安装、配置与监控
- java 数据分析库_超级好用的 Java 数据可视化库:Tablesaw
- 全球及中国金属粘合剂行业需求规模及产销前景分析报告2022-2027年
- Java反射机制01_反射的概念以及获取字节码信息 的四种方式
- 2.Spring Boot 入门
- backbone, AngularJS, EmberJS 简单比较
- Android 两个App间进行IPC通信
- LINGO 18.0安装教程
- A3的PDF试卷怎么对半拆分成A4打印?
- 关于Windows Xp的一些美化
- python中 s是什么意思_python中字符串 s[ : -1]是什么意思?
- 使用git上传代码遇到关于remote: Support for password authentication was removed on August 13, 2021.的问题
- 【沧小海笔记】之基于FPGA的以太网设计相关知识——第二章 物理层介绍(基于88E1111)
- CSS盒子模型学习-02
- python的占位符——%
- 7个你绝对没用过的超强搜索引擎
- 欢迎访问我的个人网站!
- Amy姐白富美训练营内部资料