function GetStringList1(): TStringList;
var
sl: TStringList;
i: integer;
begin
sl := TStringList.Create;
for i := 1 to 10 do
begin
sl.Add(IntToStr(i));
end;
Result := sl;
end;function GetStringList2(): TStringList;
var
i: integer;
begin
Result := TStringList.Create;
with Result do
for i := 1 to 10 do
begin
Add(IntToStr(i));
end;
end;procedure TForm1.Button3Click(Sender: TObject);
var
sl: TStringList;
begin
sl := GetStringList1;
//Memo1.Lines.Assign(sl);
Memo1.Lines := sl;
sl.Free;
end;问题1:
GetStringList1里面的局部变量sl在函数执行完成后怎么不会被free掉?
问题2:
Memo1.Lines.Assign(sl); Memo1.Lines := sl;这两个有什么区别?
解决方案 »
- 关于delphi7访问SQL同义词的怪异现象!在线等!
- delphi 窗体最大化
- veURL是什么?
- 请问怎么检测一个程序的子窗体是否显示?
- 请问什么是分组报表,Delphi中自带的QReport有分组报表功能吗?
- 大家帮帮忙!急...
- 大家来谈一下网吧管理软件
- 请问onkeypress 事件 和 onkeydown事件 的差别
- 关于数组问题,大家帮下忙,在线等
- 高分求救:access 数据库怎样添加用户,并设置密码啊,为什么delphi中我的ado连接只能使用不带密码的admin,其他都报错啊?
- 请问哪里有windous xp系统字体文件下载,就是app963的文件
- 【CSDN开心辞典】水分(非技术分)最多的ID是谁?
delphi从TObject中继承过来的在局部过程中都不会释放掉,类似于C中的static声明的变量
function GetButto(): TButton;
var
sl: TButton;
begin
sl := TButton.Create(Nil);
sl.caption := '123';
Result := sl;
end;
这个也是一样
最好不要把TStringList当做返回类型。
是因为你自己安排了内存给 TStringList 也就是 创建出来了。 你自己没有把他给Free掉。 系统不会帮你Free掉你创建出来的东西。
这句话就如同执行了下面的东西
Memo1.Lines.Clear;
for i:= 0 to s1.count -1 do
begin
Memo1.lines.add(s1[i])
end;另外对于Memo1.Lines := sl在这里实际效果是一样 , 关键是你需要检查源码, 你可以看一下Memo的成员Lines的write 方法实际上是执行以下代码
property Lines: TStrings read FLines write SetLines;procedure TCustomMemo.SetLines(Value: TStrings);
begin
FLines.Assign(Value);
end;
不会的, 你可以查看代码, 一般情况这样的写法确实会导致人有这样的误解, 但是对于Memo对象它的Lines属性有Setter, 它不是直接替换引用, 而是调用了assign, 所以不会发生内存报错
就这你的问题简单说下。
你程序中的sl,实际上是一个4字节的指针
sl := GetStringList1;
这句的意思是:在GetStringList1函数中,创建了一个TStringList对象实例(注意,这个对象本身所占据的内存是在堆中开辟的),然后将指向这个对象实例的指针返回来(也就是指向这个对象实例所占用内存的首地址),并将这个地址的值赋值给sl
这里,sl是个局部变量,是在栈中分配的,大小是4字节(你可以sizeof(sl)看看)
函数结束了,sl本身是被释放了,但是作为sl所指向的那个TStringList类并没有被释放,这个时候,因为没有任何一个变量保存这个TStringList对象实例的地址,因此也就造成了内存泄露。其实,你要是明白了我上面说的内容,也就不难理解
memo1.lines := sl
这句是干什么了,他是将sl所指向的TStringList对象实例的首地址的值赋值给了Lines。
这么赋值是不对的,memo1的Lines并不是TStringList类型的类,但是Lines和TStringList都是TStrings的子类。Lines在Memo1创建的时候,就已经被创建了,你这么赋值,就导致Lines指向的原来的那个对象实例丢了(注意,是丢了,不是被释放了,其所占的内存依然还在,但是没有变量指向他了,也就是说内存泄露了)。
因此,这种赋值,只能使用
Memo1.Lines.Assign(sl);
看8楼的回复,memo1.lines := sl 和 Memo1.Lines.Assign(sl); 是一回事,呵呵。
其实,搞清楚对象类型变量和对象之间的关系,其他的事情都好处理了。
兄弟手误了吧应该是Assign吧
如果没有释放,不用担心,在Application退出后,这些内存空间会被操作系统回收的
其他像GetMem(),New()等也是如此!而一些基本数据类型,结构体等,是在栈上分配内存,函数退出后,会自动释放内存的。