RT,有这样的定义
type
TPointData = array of Pointer;
end;var FData : TPointerData;
i : integer;
在程序里面动态添加数组元素setlength(Fdata,length(FData) + 1);
FData[length(FData) - 1] := pointer(i);如果是整形的则没问题,之后可以正常访问FData[i]的值如果是将字符串赋给指针则之后出现乱码
var str : string;
setlength(Fdata,length(FData) + 1);
FData[length(FData) - 1] := pointer(str);
在程序段中showmessage(string(FData[length(FData) - 1]));是正常的,但我在其它地方用到这个数组时,就出现乱码如果是静态数组,则直接
new(Fdata[i]);
然后赋值搞得我都糊涂了,具体要怎么做才能正常显示???我在动态数组中NEW()会出错,不知道为什么。
type
TPointData = array of Pointer;
end;var FData : TPointerData;
i : integer;
在程序里面动态添加数组元素setlength(Fdata,length(FData) + 1);
FData[length(FData) - 1] := pointer(i);如果是整形的则没问题,之后可以正常访问FData[i]的值如果是将字符串赋给指针则之后出现乱码
var str : string;
setlength(Fdata,length(FData) + 1);
FData[length(FData) - 1] := pointer(str);
在程序段中showmessage(string(FData[length(FData) - 1]));是正常的,但我在其它地方用到这个数组时,就出现乱码如果是静态数组,则直接
new(Fdata[i]);
然后赋值搞得我都糊涂了,具体要怎么做才能正常显示???我在动态数组中NEW()会出错,不知道为什么。
解决方案 »
- delphi 修改定义了DBGrid的列后不能显示查询结果
- 如何实现在CXgrid符合条件的行变色?
- 100请教:FASTREPORT2.5,页面设置后,会出现计算无数页面,好象有无数页面要打印?
- 如何在打开一个窗体前先判断另一个窗体是否存在?
- Delphi6+DOA+Oracle8如何处理并发性问题
- 关于c/s模式的问题
- word 文档的提示-100分
- 请教一些Delphi的基本问题(2)
- Frend(一刀),兄弟给你支招!
- delphi中如何实现多线程socket通信时
- Ehlib的Demo1里,DBGridEh1的Vendor Number列STFilter什么都没指定,但在设计期就有下拉箭头,是如何做到的?
- Mouse_Event 鼠标点击点问
FData[length(FData) - 1] := pointer(str);Pointer是无类型的,对于Delphi自动管理的类型(如string,array,record),强制使用Pointer转换并不会增加变量的引用计数,等到变量被回收了,再使用指针来访问就可能会得到垃圾数据。
function _New(size: Longint; typeInfo: Pointer): Pointer;
当你调用New(PTypeVar)的时候,会隐含传入SizeOf(PTypeVar^)、TypeInfo(PTypeVar^)两个参数,其中后一个是供Initialize用的。你认为SizeOf(Pointer^)应该是多少,编译器能猜出来么?
items.addobject();这个方法,任何类型的都可以加进去,到底是什么原理?
还有就是
setlength(Fdata,length(FData) + 1);
FData[length(FData) - 1] := pointer(i);
这样又为什么可以呢?解决方法个人推荐使用PChar来存取,当然用PString来弄也可以 ------------------------------------------------------放到数组里?FData[length(FData) - 1] := pchar(str);
一样的....
当使用显示转换将string类型转成其它指针类型的时候,并不会增加它的引用计数,生存期结束后该释放就释放了
如果你不知道PChar和StrNew/StrDispose的话,那还是用PString和NewStr/DisposeStr吧……
TarrayVariant = array of PChar;
FarrayVariant :TarrayVariant ;
For i := 0 to 1o do
begin
DriveString := '测试' + inttostr(i);
SetLength(FarrayVariant,Length(FarrayVariant) +1 );
FarrayVariant[Length(FarrayVariant) -1 ] := strNew(PChar(DriveString)) ;
end;FarrayVariant 为全局变量,在其它代码段中调用时,这样是可以正常显示,但是要怎么释放这些内存?StrDispose 不知道怎么用另外一个就是刚刚说的,这种要以什么类型的形式存入数组中?
谢谢!!
你用个LIST 去添加试下
var
p: PChar;
begin
p := StrNew(PChar('hello'));
StrDispose(p);
end;
對于基礎類型,可以通過varType取得。若是復雜類型(如class),無法直接獲得,若是對象,可通過所記錄的地址(類型為varLongWord),訪問負偏移地址vmtTypeInfo可以取得類型信息,如PPointer(Integer(v[i]) + vmtTypeInfo)^。
这是我的释放的代码,运行到某些元素下标时会报错,无效指针、、不知为何
for i := low(FList) to High(FList) do
begin
StrDispose(pchar(Flist[i]));
end;
起先也是考虑用变体类型,可是里面要存放类对象。
我想先试一下指针数组的方法可行不
type
TarrayPointer = array of Pointer;
var Flist : TarrayPointer ;这种可否采用这种方法,将类对象存入到数组中?
就是先申请内存,将对象拷入内存块,然后再赋给数组,能否行得通不?
对于值变量(如Integer、Int64,作为局部变量、参数时分配在栈上),最稳妥的方法是重新分配一块内存保存这个值。如:
var
p: PInteger;
n: Integer;
begin
n := 2;
New(p); // 使用New手工分配内存时,所传递的指针参数必须是有类型的,这样编译器才知道要给变量分配多大的内存
p^ := n; // 将变量n的值拷贝到指针p所指向的内存的值
Dispose(p); // 手工释放内存
end;而对于引用类型(如string、对象实例),只要保存引用的地址就可以了。如:
var
obj: TObject;
p: Pointer;
begin
//...
p := obj;
end;这里顺便提一下,Delphi里面有些类型(如string、array)是由编译器自动维护引用计数的,如果使用无类型的Pointer则需要注意这一点(可能会引用无效的值)。2. 如何知道某个数组元素的类型?
很显然,如果数组定义成array of Pointer,我们是没办法知道元素所代表的实际类型的。明白了上面两点,问题就简单多了。我们先看看最简单的方法:
type
TDataArray = array of Variant;这种方法可以保存Delphi内大多数的简单类型的值,而且无需管理内存,但美中不足的是Variant不能直接保存对象实例的地址。当然,这个时候可以按照楼上的变通一下,采用某种类型来保存对象实例的地址,使用时再强制转换即可。另有一种方法就是使用TVarRec:
type
TDataArray = array of TVarRec;
这种方式支持Delphi的部分复杂类型(如Class),但需要手工分配及释放内存,而且操作上比较麻烦,需先根据VType判断类型,且不能想Variant那样直接赋值。还有一种方法就是自己封装一个结构。当然,如果可行的话,我建议使用对象来封装。如:TDataObject = class
protected
function GetAsString: string; virtual; abstract;
public
property AsString: string read GetAsString;
//...
end;TInteger = class(TDataObject)
//...
end;TDataArray = array of TDataObject; // 如果使用TObjectList更方便。
var
obj: TObject;
p: Pointer;
begin
//...
p := obj;
end;
这种方法是不是不用自己去分配和管理内存?还有就是
var FarrayVariant : array of pointer;
For i := 0 to 1o do
begin
DriveString := '测试' + inttostr(i);
SetLength(FarrayVariant,Length(FarrayVariant) +1 );
FarrayVariant[Length(FarrayVariant) -1 ] := strNew(PChar(DriveString)) ;
end;
For i := 0 to 1o do
begin
StrDispose(Pcahr(FarrayVariant[i]));
end;
这个释放的操作,怎么内存好像没有任何变化?就是不管执不执行这个操作,内存没有变化那最后,我是不是可以采用这种方式来保存字符串和类对象?而对于引用类型(如string、对象实例),只要保存引用的地址就可以了。如:
var
obj: TObject;
p: Pointer;
begin
//...
p := obj;
end; -----------
非常感谢!!
var
obj: TObject;
p: Pointer;
begin
obj := TObject.Create;
try
p := obj; // p和obj指向了同样的地址,使用TObject(p)和obj效果相同
finally
FreeAndNil(obj); // 现在p所指向的内存已经被释放,再使用p可能会导致内存访问错误。
end;
end;严格的来说,声明指针变量时,编译器已经为这个指针变量*本身*分配了内存。给这个指针赋值时(p:=obj;),实际上是把obj所引用的对象实例的地址保存到这个指针变量内。(呵呵,也就是说:指针变量的值保存的是某个对象实例的地址)。但字符串和对象不同(由于字符串由Delphi自动管理创建和释放,引用计数为0时自动释放),需要分配内存:
procedure Test;
var
str: string;
p: PString; // 声明为PString,可以利用string的引用计数;如果为PChar,使用StrNew,则会重新拷贝内容。
begin
str := IntToStr(12345); // 此时字符串的引用计数为1
New(p);
p^ := str; // 此时字符串的引用计数为2
Dispose(p); // 此时字符串的引用计数为1
end; // 离开作用域后字符串引用计数为0,自动释放内存。2. 内存没有变化是指哪块内存?调用Dispose或StrDispose只负责释放指针所指向的那块内存,并没有把指针置为nil,如果再使用这个指针,*可能*会导致无效访问(当然,因为长字符串的内容分配在堆上,当这块内存还没有被覆盖时,数据还是正确的,但这块内存区域应该已经标记为不可用了(个人猜测))。3. 前面已经说了,使用无类型的Pointer,无法知道元素的实际类型。
1.那这种操作是不是有必要的?
var FarrayVariant : array of pointer;
For i := 0 to 1o do
begin
DriveString := '测试' + inttostr(i);
SetLength(FarrayVariant,Length(FarrayVariant) +1 );
FarrayVariant[Length(FarrayVariant) -1 ] := strNew(PChar(DriveString)) ;
end;
有没有必要进行手动释放?
For i := 0 to 1o do
begin
StrDispose(Pcahr(FarrayVariant[i]));
end; 2.对于对象实例来说,obj实际上是一个有类型的指针,所以
var
obj: TObject;
p: Pointer;
begin
obj := TObject.Create;
try
p := obj; // p和obj指向了同样的地址,使用TObject(p)和obj效果相同
finally
FreeAndNil(obj); // 现在p所指向的内存已经被释放,再使用p可能会导致内存访问错误。 那如果不释放这个对象,在其它地方访问是不是正常的?
end;
end;3.我释放前面申请的内存,并把数组长度设为0 在任务管理器里看不到内存使用的变化呢,