提供对象作为函数结果是否安全?

lyb*_*rko 3 delphi

在这里,我提供简单的代码.

function GetStringList:TStringList;
var i:integer;
begin
   Result:=TStringList.Create;
   Result.Add('Adam');
   Result.Add('Eva');
   Result.Add('Kain');
   Result.Add('Abel');
end;


procedure ProvideStringList(SL:TStringList);
var i:integer;
    Names:TStringList;
begin
   Names:=TStringList.Create;
   Names.Add('Adam');
   Names.Add('Eva');
   Names.Add('Kain');
   Names.Add('Abel');
   SL.Assign(Names);
   Names.Free;
end;


procedure TForm1.btn1Click(Sender: TObject);
var SL:TStringList;
    i:integer;
begin
   SL:=TStringList.Create;
   SL.Assign(GetStringList);
   for i:=0 to 3 do ShowMessage(SL[i]);
   SL.Free;
end;


procedure TForm1.btn2Click(Sender: TObject);
var SL:TStringList;
    i:integer;
begin
   SL:=TStringList.Create;
   ProvideStringList(SL);
   for i:=0 to 3 do ShowMessage(SL[i]);
   SL.Free;
end;
Run Code Online (Sandbox Code Playgroud)

现在的问题是:函数GetStringList中的结果对象会发生什么:Tstringlist,它被创建,但从未被释放?(我调用2次C​​reate并且只有1次Free)是按照函数提供对象的内存安全吗?还是我应该使用过程来执行此任务,其中只是处理对象创建和销毁(过程ProvideStringlist)?我叫2次创建和2次免费.还是有其他解决方案吗?

Thanx提前

Lyborko

Hei*_* Z. 7

提供对象作为函数结果是否安全?

这是可能的,但它需要来自实现者和呼叫的关注.

  1. 为调用者清楚,他控制返回对象的生命周期
  2. 当功能失败时,请确保您没有内存泄漏.

例如:

function CreateBibleNames: TStrings;
begin
  Result := TStringList.Create;
  try
    Result.Add('Adam');
    Result.Add('Eva');
    Result.Add('Kain');
    Result.Add('Abel');
  except
    Result.Free;
    raise;
  end;      
end;
Run Code Online (Sandbox Code Playgroud)

但在Delphi中,最常见的模式是:

procedure GetBibleNames(Names: TStrings);
begin
  Names.BeginUpdate;
  try
    //perhaps a Names.Clear here
    //but I don't use it often because the other
    //way is more flexible for the caller

    Names.Add('Adam');
    Names.Add('Eva');
    Names.Add('Kain');
    Names.Add('Abel');
  finally
    Names.EndUpdate;
  end;      
end;
Run Code Online (Sandbox Code Playgroud)

所以调用者代码可能如下所示:

procedure TForm1.btn1Click(Sender: TObject);
var
  Names: TStrings;
  i:integer;
begin
  Names := CreateBibleNames;
  try
    for i := 0 to Names.Count -1 do 
      ShowMessage(Names[i]);
  finally 
    Names.Free;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

和另一个更常见的版本:

procedure TForm1.btn1Click(Sender: TObject);
var
  Names: TStrings;
  i:integer;
begin
  Names := TStringList.Create;
  try
    GetBibleNames(Names);
    for i := 0 to Names.Count -1 do 
      ShowMessage(Names[i]);
  finally 
    Names.Free;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

(我目前没有编译器,所以也许有一些错误)


小智 5

我不知道你的意思是安全的,但这是常见的做法.函数的调用者负责释放返回的对象:

var
   s : TStringList; 
begin
   s := GetStringList;
   // stuff
   s.free;
end;
Run Code Online (Sandbox Code Playgroud)

  • 你应该在这里添加一个`try ... finally`块.此外,更常见的做法是让调用者创建对象并将其传递给方法以将"Create"和"Free"放在一起. (2认同)