类的实例在使用过程中,需要对它里面的值全清除后重赋值,
其中,字符串类型的成员用 CleanupInstance 可以全清空,
那其它类型如何处理?不会是一一赋空吧?呵呵
其中,字符串类型的成员用 CleanupInstance 可以全清空,
那其它类型如何处理?不会是一一赋空吧?呵呵
解决方案 »
- Delphi7如何调用Word2007另存为PDF的功能
- 数据刷新显示
- JRHT今天过生日-_-|| 要放点血了
- 如何对两个表同时进行数据的刷新!~~~
- 在C/S结构中,查询数据的问题?
- sql语句,往oracle数据库中插入时间数据?
- 关于报表显示及怎么求得两日期相隔多少天、小时的问题?
- 关于打印报表时如何使结果为0的字段不显示?
- 如何创建VPN的拨号连接(在DELPHI)
- 动态修改ADOConnection.ConnectionString 为何不行?SocketConnection.Address,Port为何不行?
- 关于Treeview展开用panel做显示问题
- dxorgchart特殊功能
Buffer: array[0..255] of Byte;
Obj: TMyObject;
begin
//填充调试内容
FillChar(Buffer, sizeof(buffer),$cc); //清理内存
FillChar(Buffer[0], TMyObject.InstanceSize,0); //给对象指针指向有效的内存,相当于分配内存
Obj := @Buffer[0];
Obj := TMyObject(TMyObject.InitInstance(Obj));
Obj.A := 65;
Obj.B[0] := 'a';
Obj.B[1] := '0';
Obj.B[2] := '1';
Obj.B[3] := 'c';
Obj.B[4] := 'f';
Obj.B[5] := '8';
Obj.B[6] := '9';
Obj.B[7] := #0;
//这里请不要释放Obj
ShowMessage(PAnsiChar(@Buffer[8])); //清理内存
FillChar(Buffer[0], TMyObject.InstanceSize,0); //给对象指针指向有效的内存,相当于重新分配内存
Obj := @Buffer[0];
Obj := TMyObject(TMyObject.InitInstance(Obj));
Obj.A := 65;
Obj.B[0] := 'B';
Obj.B[1] := '0';
Obj.B[2] := '1';
Obj.B[3] := 'c';
Obj.B[4] := 'f';
Obj.B[5] := '8';
Obj.B[6] := '9';
Obj.B[7] := #0;
//这里请不要释放Obj
ShowMessage(PAnsiChar(@Buffer[8]));
end;
constructor TMyObject.Create;
begin
//这里只做简单演示,实际的代码当中,这里应当有一行"Inherited;"等类似的代码
A := 100;
end;然后把对成员A的赋值去掉
var
Buffer: array[0..255] of Byte;
Obj: TMyObject;
begin
//填充调试内容
FillChar(Buffer, sizeof(buffer),$cc); //清理内存
FillChar(Buffer[0], TMyObject.InstanceSize,0); //给对象指针指向有效的内存,相当于分配内存
Obj := @Buffer[0];
Obj := TMyObject(TMyObject.InitInstance(Obj));
//Obj.A := 65;//去掉给成员A的赋值
Obj.B[0] := 'a';
Obj.B[1] := '0';
Obj.B[2] := '1';
Obj.B[3] := 'c';
Obj.B[4] := 'f';
Obj.B[5] := '8';
Obj.B[6] := '9';
Obj.B[7] := #0;
//这里请不要释放Obj
ShowMessage(IntToStr(Obj.A));//查看成员A的值 //清理内存
FillChar(Buffer[0], TMyObject.InstanceSize,0); //给对象指针指向有效的内存,相当于重新分配内存
Obj := @Buffer[0];
//这里把代码改一下对TMyObject的构造函数进行调用
//Obj := TMyObject(TMyObject.InitInstance(Obj));
Obj.Create;//注意这一行代码 //Obj.A := 65;//去掉对成员A的赋值
Obj.B[0] := 'B';
Obj.B[1] := '0';
Obj.B[2] := '1';
Obj.B[3] := 'c';
Obj.B[4] := 'f';
Obj.B[5] := '8';
Obj.B[6] := '9';
Obj.B[7] := #0;
//这里请不要释放Obj
ShowMessage(IntToStr(Obj.A));//查看成员A的值
end;然后再进行如下测试:
var
Obj: TMyObject;
begin
Obj := TMyObject.Create;//正常构造 ShowMessage(IntToStr(Obj.A)); //清理内存
FillChar(Pointer(Obj)^, TMyObject.InstanceSize,0); //重新构造
Obj.Create;
ShowMessage(IntToStr(Obj.A));
end;
谢谢unsigned , 消化下先。呵呵。
问题是,如果你的对象中包含带引用计数的成员(比如字符串)或者你的类中包含类,这么初始化会导致这些带引用计数的变量不能正确更新他们的引用计数以及类不能被正确释放而导致内存泄漏。另外,如果你的类实现了接口,还需要你按照正确的顺序在对象所指向的内存中初始化接口,这个顺序,Delphi并没有形成文档,也就是说,不同的Delphi版本可能代表这不同的顺序。
注意,使用这种方法的限制很多,在注释中给出的,仅仅是一部分限制。
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}type
TMyObject = class(TObject)
private
FA: Integer;
FB: Char;
FC: Byte;
FD: Word;
procedure SetA(const Value: Integer);
procedure SetB(const Value: Char);
procedure SetC(const Value: Byte);
procedure SetD(const Value: Word);
public
property A: Integer read FA write SetA;
property B: Char read FB write SetB;
property C: Byte read FC write SetC;
property D: Word read FD write SetD;
end;{ TMyObject }procedure TMyObject.SetA(const Value: Integer);
begin
FA := Value;
end;procedure TMyObject.SetB(const Value: Char);
begin
FB := Value;
end;procedure TMyObject.SetC(const Value: Byte);
begin
FC := Value;
end;procedure TMyObject.SetD(const Value: Word);
begin
FD := Value;
end;{ TForm1 }procedure TForm1.Button1Click(Sender: TObject);
var
Obj: TMyObject;
begin
Obj := GetMemory(TMyObject.InstanceSize);//根据类的大小开辟一块内存
try
ZeroMemory(Obj, TMyObject.InstanceSize);//初始化这块内存 //这个过程可以完成对象的初始化,如果调用了这个,那么记得在最后需调用 CleanupInstance
//他们是一对,这个调用不是必须的,视情况而定,
//如果这里没有调用 InitInstance 则后门就不需要调用 CleanupInstance
TMyObject.InitInstance(Obj);
try
//实际上,上面三个步骤(开辟内存,初始化内存,调用InitInstance完成的就是 NewInstance 所完成的工作)
//这里调用Create仅仅是为了完成Create中对类中成员的初始化
//但是 Delphi 却没有提供与之对应的可以释放类中成员占用的堆中的内存的调用
//形式上 Destroy 似乎和 Create 对应,
//但是 以对象的方式调用 Create 并不创建内存(TMyObject.Create 才创建内存),
//仅仅是完成用户定义在 Create 实现过程中的初始化而已
//而以对象的方式调用 Destroy 却真正释放了对象占用的内存
Obj.Create; Obj.A := 100; ShowMessage(IntToStr(Obj.A)); //这里是清空刚刚的那个类的成员
//仅仅是清空,
//如果类中包含对象成员,则对象成员不会被释放
//类中包含指针成员,指针指向的内存也不会被释放
//类中包含字符串或者动态数组,则其占用的内存也不会被释放
//类中包含接口,则接口的引用计数不会变化
//总之,如果你这个类中的成员在堆中开辟了内存,那么这些内存都不会被释放
// 并且引用计数类型的成员变量其引用计数也不会变化
ZeroMemory(Obj, TMyObject.InstanceSize);
TMyObject.InitInstance(Obj);
Obj.Create;
ShowMessage(IntToStr(Obj.A));
finally
Obj.CleanupInstance;
end;
finally
FreeMemory(Obj); //记得用完了释放内存
end;
end;end.
其实,你说的先释放再创建会很慢,可能是你的 Create 中做了很多工作导致创建变慢,如果你的应用频繁地需要创建、释放,那你可以优化你的Create,有些成员变量,完全可以用到了再初始化,没有必要非得在Create中一次都初始化了
一般来说,创建和释放对象的时候,初始化和清理工作消耗的时间远大于申请和释放内存的时间。如果只是为了省掉那么一小块时间,折腾太多工作得不偿失。你更应该做的是设计好你的类,而不是弄些出了问题都不好调的 trick。
我一直都是这么做:)