s在窗体中声明为tstrings;procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Lines:=NineNineMultiTable;
s.Free; <-这里能够正确执行
end;function TForm1.NineNineMultiTable:TStrings;
var
i,j:Integer;
cs: string;
begin
i:=1;
s:=TStringList.Create;
s.BeginUpdate;
for i := 1 to 9 do
begin
j:=1;
cs:='';
while (j<=i) do
begin
cs:= cs + ' ' + IntToStr(j)+'× '+IntToStr(i)+'='+IntToStr(j*i);
Inc(j);
if (i<j) then
begin
s.Add(cs);
s.Add('');
end;
end;
end;
s.EndUpdate;
Result:=s;
//s.Free;<-放这里则不能执行,对象被释放掉了
end;谁能解释一下放在这两个地方的区别在哪儿?本来想把s的定义放在函数内部,因为是临时对象,但就因为这个问题放窗体里了。
begin
Memo1.Lines:=NineNineMultiTable;
s.Free; <-这里能够正确执行
end;function TForm1.NineNineMultiTable:TStrings;
var
i,j:Integer;
cs: string;
begin
i:=1;
s:=TStringList.Create;
s.BeginUpdate;
for i := 1 to 9 do
begin
j:=1;
cs:='';
while (j<=i) do
begin
cs:= cs + ' ' + IntToStr(j)+'× '+IntToStr(i)+'='+IntToStr(j*i);
Inc(j);
if (i<j) then
begin
s.Add(cs);
s.Add('');
end;
end;
end;
s.EndUpdate;
Result:=s;
//s.Free;<-放这里则不能执行,对象被释放掉了
end;谁能解释一下放在这两个地方的区别在哪儿?本来想把s的定义放在函数内部,因为是临时对象,但就因为这个问题放窗体里了。
//s放在函数内部就行了
function TForm1.AddContent:TStrings;
begin
Result:=TStringList.Create; Result.Add('111');end;procedure TForm1.btn1Click(Sender: TObject);
begin
memo.Lines:=AddContent;
end;
帮你改改逻辑,s做为临时变量,由调用方面负责创建和释放.
procedure TForm1.Button1Click(Sender: TObject);
var
s: TStrings;
begin
s := TStringList.Create; {创建}
NineNineMultiTable(s); {操作}
Memo1.Lines := s; {使用}
s.Free; {用完才释放}
end;procedure TForm1.NineNineMultiTable(out s: TStrings);
var
i, j: Integer;
cs: string;
begin
s.BeginUpdate;
for i := 1 to 9 do
begin
j := 1;
cs := '';
while (j <= i) do
begin
cs := cs + ' ' + IntToStr(j) + ' × ' + IntToStr(i) + ' = ' + IntToStr(j * i);
Inc(j);
if (i < j) then
begin
s.Add(cs);
s.Add('');
end;
end;
end;
s.EndUpdate;
end;
这时memo.Lines:=NineNineMultiTable,memo.lines就接管了TStringlist创建的引用,使用memo.lines就能访问在局部过程中创建的堆内存了!
有了这个依据,我想楼主自己想想就应该能明白了!
b:= '';
那a也等于''吗??发现问得好怪喔.
如果象楼上JPEXE所说,那s.free放在两个地方都可以才对呀?
JPEXE在4楼的回复给我很好的思路,谢谢!
FLines: TStrings;procedure SetLines(Value: TStrings);procedure TCustomMemo.SetLines(Value: TStrings);
begin
FLines.Assign(Value);//进行对象的深度复制
end;
-----------------------
这个不是简单的指针传递,刚开始我也被迷惑了,是将TStringList进行对象clone的过程
2.有疑问是因为你不了解lines属性。看看TMemo.Lines属性的代码: property Lines: TStrings read FLines write SetLines; procedure TCustomMemo.SetLines(Value: TStrings);
begin
FLines.Assign(Value);
end; FLines是TStrings类型,所以看它的Assign方法procedure TStrings.Assign(Source: TPersistent);
begin
....
AddStrings(TStrings(Source)); ...
inherited Assign(Source);
end; 最后看AddStrings的实现: 发现是内容复制,S.free是不会影响memo.lines的内容。procedure TStrings.AddStrings(Strings: TStrings);
var
I: Integer;
begin
BeginUpdate;
try
for I := 0 to Strings.Count - 1 do
AddObject(Strings[I], Strings.Objects[I]);
finally
EndUpdate;
end;
end;
界面上的内容不显示,只是UI的展示问题。
Memo1.Lines:=NineNineMultiTable;
s.Free; <-这里能够正确执行
实际已经将Memo1.Lines给Free了,程序退出时是要出错的。正确的做法,应类似4楼