英文:
TStringlist as function result, minimal code sequence
问题
以下是您要翻译的内容:
"如何从函数返回Stringlist已经讨论了很多次。
我的代码序列版本1只是如何做的简要回顾。
function GetStrings: TStringList;
begin
Result := TStringList.Create;
Result.Add('字符串A');
Result.Add('字符串B');
end;
procedure TForm1.Button1Click(Sender: TObject);
var
stemp: TStringList;
begin
stemp := GetStrings;
MyListBox.Items.AddStrings(stemp);
stemp.Free;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
MyListBox.Items.AddStrings(GetStrings);
end;
是否有选项在版本2中修复内存泄漏而"不需要额外的代码",这种方法到底有多危险,如果我的字符串列表只包含几个字符串项,是否会导致任何故障,不会发生内存问题?"
英文:
How to return a Stringlist from a function has been discussed many time before.
My code sequence version 1 is just a recap how to do it.
function GetStrings : TStringList;
begin
Result := TStringList.Create;
Result.Add('string A');
Result.Add('string B');
end;
procedure TForm1.Button1Click(Sender: TObject);
var stemp : tStringList;
begin
stemp := GetStrings;
MyListBox.items.addstrings(stemp);
stemp.Free;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
MyListBox.items.addstrings(GetStrings);
end;
is there any option to fix the memory leak in version2 with "no extra code", how dangerous is this approach at all, will this cause any failures if my stringlist is just a few string items, out of memory issues will not happen?
答案1
得分: 14
不要使用TStringList
作为结果类型,而是使用TArray<string>
。当然,这会使version1变得过时。
function GetStrings: TArray<string>;
begin
var lst := TStringList.Create;
try
lst.Add('字符串 A');
lst.Add('字符串 B');
Result := lst.ToStringArray;
finally
lst.Free;
end;
end;
英文:
Don't use a TStringList
as result type, but a TArray<string>
. Of course this makes version1 obsolete.
function GetStrings : TArray<string>;
begin
var lst := TStringList.Create;
try
lst.Add('string A');
lst.Add('string B');
Result := lst.ToStringArray;
finally
lst.Free;
end;
end;
答案2
得分: 4
以下是翻译好的内容:
如果你打算从函数中返回一个新创建的对象,有一个模式可供使用。它如下所示:
function GetStrings: TStringList;
begin
Result := TStringList.Create;
try
Result.Add('string A');
Result.Add('string B');
except
Result.Free;
raise;
end;
end;
这个函数的行为类似构造函数。它要么返回一个新创建的对象并将所有权传递给调用者,要么引发异常并在引发之前进行清理。
如果你使用这种模式,那么你需要像使用构造函数创建的对象一样使用它,采用众所周知的模式:
procedure TForm1.Button1Click(Sender: TObject);
var
temp: TStringList;
begin
temp := GetStrings;
try
MyListBox.Items.AddStrings(temp);
finally
temp.Free;
end;
end;
现在,关于你的直接问题:
> 是否有选项在“没有额外代码”的情况下修复版本2中的内存泄漏,这种方法究竟有多危险,如果我的字符串列表只包含少量字符串项,会导致任何故障吗,不会发生内存问题吗?
如果你返回一个新创建的对象,那么调用者不能避免对该对象的所有权责任。
英文:
If you are going to return a newly instantiated object from a function, there is a pattern for that. It goes like this:
function GetStrings: TStringList;
begin
Result := TStringList.Create;
try
Result.Add('string A');
Result.Add('string B');
except
Result.Free;
raise;
end;
end;
This function behaves just like a constructor. Either it returns a newly instantiated object, and passes ownership to the caller. Or it raises an exception, and tidies up before raising it.
If you use this pattern, then you need to do so in the same way as you would with an object instantiated by a constructor, using the well known pattern:
procedure TForm1.Button1Click(Sender: TObject);
var
temp: TStringList;
begin
temp := GetStrings;
try
MyListBox.Items.AddStrings(temp);
finally
temp.Free;
end;
end;
Now, as for your direct question:
> is there any option to fix the memory leak in version2 with "no extra code", how dangerous is this approach at all, will this cause any failures if my stringlist is just a few string items, out of memory issues will not happen?
If you do return a newly instantiated object, then the caller can't avoid the responsibilities of ownership for that object.
答案3
得分: 4
如其他人所提到的,您需要在函数和调用者两处添加额外的代码,以正确管理TStringList
,以确保它始终被释放。
更好的选项是根本不返回TStringList
,而是接受调用者想要的任何TStrings
对象,然后只需填充它,例如:
procedure GetStrings(Strings: TStrings);
begin
Strings.BeginUpdate;
try
Strings.Add('string A');
Strings.Add('string B');
finally
Strings.EndUpdate;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
GetStrings(MyListBox.Items);
end;
英文:
As others as mentioned, you need to add extra code to both the function and the caller in order to manage the TStringList
correctly to ensure it is always freed.
A better option is to not return a TStringList
at all, but rather to take in any TStrings
object the caller wants and just fill it in, eg:
procedure GetStrings(Strings: TStrings);
begin
Strings.BeginUpdate;
try
Strings.Add('string A');
Strings.Add('string B');
finally
Strings.EndUpdate;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
GetStrings(MyListBox.Items);
end;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论