用函數返回一個TStringList類型的值﹐正確的應該怎么做﹖(30分)

  • 主题发起人 主题发起人 dadabox
  • 开始时间 开始时间
虽然从语法上说,类类型作为函数的返回值是可以的,但这会引起许多问题。
因为类是静态装入内存中的,当创建一个对象时,将把类的属性复制1份到内存中并初始化,新的对象指
向这片区域,对象的格式为类地址(4字节)+对象属性,所以所有对象共享方法而拥有不同的属性,也可
以在运行时确定对象的类型信息。
正因为对象实际上是指针,所以下面程序执行后
function list():Tstringlist;
var
;s:tstringlist;
begin
; s:=tstringlist.Create;
; s.Add('s1');
; s.Add('s2');
; result:=s;
; s.free;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
; listbox1.Items:=list;
end;
result和S指向同一片内存区域,S虽然正确释放,同时result也不能返回正确结果。
若将s.free语句去掉,虽然可返回正确结果,但是第二次执行button1Click时,
listbox1.Items将指向新的list值,原来的listbox1.items不能释放。 ;

function list():Tstringlist;
var
;s:tstringlist;
begin
; s:=tstringlist.Create;
; s.Add('s1');
; s.Add('s2');
; result:=s;
; s.free;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
; i:integer;
begin
; for i:=0 to ;100000 do
; listbox1.Items:=list;
end;
执行以上程序时,虽然不能返回正确结果,但用任务管理器查看,程序大小在2M左右。
将s.free去掉后,程序能返回正确结果,但程序超过10M!!!
因此,小弟认为,不要用类变量作为函数的返回值,可以用过程代替。
 
procedure TForm1.Button1Click(Sender: TObject);
var
; i:integer;
begin
; for i:=0 to ;100000 do
; listbox1.Items:=list; ; ; ; ; ; ; <-------注意这里
end;
list方法执行之后,将不断地Create,如果没有执行free,其后果是不可想象的!
我在上面已经写了两种解决的方法,除此之外,我实在想不到更好的办法了。
我编码的习惯就是需要返回值就用函数,不需要就用过程。

附:
我不能收信了,邮箱完全正常。
如果不是大富翁不稳定的话(无法从"问题列表"登录),可能我不会再看到这帖子。
 
to 影子
对于你上面的程序
procedure TForm1.Button1Click(Sender: TObject);
var
; ss : TStringList;
begin
; ss := test;
; listbox1.Items := ss; <-------注意这里
; ss.Free;
end;

依然存在不能正确释放的问题,如我上所述,第二次执行button1Click时,
listbox1.Items将指向新的ss值,原来的listbox1.items不能释放。 ;
;for i:=0 to ;100000 do 即为测试是否正确释放而写的。将你的程序改成如下
procedure TForm1.Button1Click(Sender: TObject);
var
; ss : TStringList;
; i:integer;
begin
; for i:=0 to 100000 do
; begin
; ; ss := test;
; ; listbox1.Items := ss;
; ; ss.Free;
; end;
end;
执行后用任务管理器查看,你会发现程序大了很多,
所以小弟仍然坚持我的观点,不要用类类型作为函数的返回值,用过程代替。
 
{如果用了ss.Free;就算for循环之后,程序占用的内存并不增加多少,
而不用ss.Free;所占用的内存会剧增。可见,ss.Free;起了释放的作用。
看看下面的程序及最后的解释}

unit Unit1;

interface

uses
; Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
; Dialogs, StdCtrls;

type
; TForm1 = class(TForm)
; ; Button1: TButton;
; ; ListBox1: TListBox;
; ; Button2: TButton;
; ; Button3: TButton;
; ; procedure Button1Click(Sender: TObject);
; ; procedure Button2Click(Sender: TObject);
; ; procedure Button3Click(Sender: TObject);
; private
; ; ss,tt : TStringList;
; ; function ;test: TStringList;
; public
; ; { Public declarations }
; end;

var
; Form1: TForm1;

implementation

{$R *.dfm}

function ;TForm1.test: TStringList;
begin
; ss := TStringList.Create;
; ss.Add('aaaaa');
; ss.Add('bbbbb');
; result := ss;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
; if assigned(tt) then
; ; listbox1.Items.AddStrings(ss);
end;

procedure TForm1.Button2Click(Sender: TObject); ; ;//初始化
begin
; ss := test;
; tt := ss;
; //ss.Free;
; listbox1.Clear;
end;

procedure TForm1.Button3Click(Sender: TObject); ; ;//释放ss
begin
; tt.Free;
end;

end.

{将ss,tt改为全局对象,先执行Button2Click初始化。
点击Button1,可以看到ListBox1中增加了内容,再点击时继续增加。
点击Button3之后,如果再点击Button1,将会出错!
资源确切地被释放了。}
 
呵呵,for循环之后,程序占用的内存确实并不增加多少,小弟弄错了。[:D][:D][:D]
小弟原以为listbox1.items是直接指向ss,实际上是将ss的值复制了一份.
给listbox1.items直接赋值实际上是
listbox1..items.clear;
listbox1.items.addstrings();
这两个方法。
因此可在调用函数后将资源释放掉,而不是在内部。
 
我不在乎分数,我更喜欢讨论!
老师领入门,修行靠自己!
从我最早的回复到最后的回复,
使我明白了不少当初模糊的问题。
感觉真好!
 
有那么麻烦吗?stringlist是什么?有人看过源码吗??
function test: string; //string和stringlist有区别吗?
begin
// ;Result:=TStringList.Create;
; Result := 'aaa';
; Result := Result + #13#10'aaa';
; Result := Result + #13#10'aaa';
; Result := Result + #13#10'aaa';
end;

procedure tform1.button1click(sender: tobject);
var
; temp: TStringList;
begin
; temp := TStringList.Create;
; Temp.Text := test;
; temp.Free;
end;

一个函数返回TStringList跟返回String并不是有很大差别的吧,至少有些时候:)
;
 
你是对的!
仅仅从返回来看,没有区别,只是dadabox要求返回TStringList。
一个在函数里Create,另一个在调用的方法里Create!
假如在函数里用TStringList对字符串操作之后,很多人都会懒得转回String返回吧?
 
function getpmid(mid:string;var lst:tstringlist):boolean;

function getcmid(mid:string;var lst:tstringlist):boolean;
var
qry:tquery;
begin
; qry:=tquery.create(application);
; lst.clear;
; ;with qry do
; ;begin
; ; ;databasename:='DB_Server';
; ; ;close;
; ; ;sql.text:='select mid from menu where mid like '''+mid+'%'' and ismodule=0 order by mid';
; ; ;open;
; ; ;first;
; ; ;if not IsEmpty then
; ; ; ; while not eof do
; ; ; ; begin
; ; ; ; lst.Add(fields[0].asstring);
; ; ; ; next;
; ; ; ; end;
; ;end;
; ;if lst.count<>0 then result:=true else result:=false;
end;


function do(mid:string):boolean;
var
lst:tstringlist;
i:integer;
begin
lst:=tstringlist.create;
if not getcmid(mid,lst) then exit;
else begin
; for i:=0 to lst.count-1 do
begin
; if lst.strings='welcome' then result:=true
; break;
else result:=false;
end;
 
謝謝各位的熱心﹐但此題分數并不多﹐不如只給一個人了。其中影子最為熱心﹐所以
我決定全給他了。謝謝各位的熱心參與﹗
 
后退
顶部