如何在函数之间传递对象?

Al *_*l C -1 delphi object lazarus

假设我有一个功能:

function someFunction: TStringList;  
begin  
  result:=TStringList.Create;  
  if someConditionIsTrue then  
    result:=doSomething;  
  //other code  
end; 
Run Code Online (Sandbox Code Playgroud)

功能doSomething:

function doSomething: TStringList;
begin
  result:=TStringList.Create;
  result.Add(something);
end;
Run Code Online (Sandbox Code Playgroud)

如果我运行这个代码,一切都按预期工作,但我仍然想知道这是否是传递像stringlist这样的对象的"正确"方法?

字符串列表永远不会被释放,我想知道在调试或其他人试图理解代码时,以这种方式传递对象会变得复杂或混乱.

Jer*_*dge 6

"正确"的方法是让你建立自己的规则来解决事情的破坏.在函数结果中创建对象很好,但前提是您遵循自己的严格规则.

在您的情况下,SomeFunction有内存泄漏.首先,您创建一个TStringList,然后如果满足某些条件,则TStringList在其位置创建另一个条件,完全忽略第一个条件.因此,泄漏记忆.

DoSomething如果您可能已经创建了一个字符串列表,则该函数不应该是返回字符串列表的函数.相反,只需将其作为一个程序......

procedure DoSomething(AList: TStringList);
begin
  AList.Add(Something);
end;
Run Code Online (Sandbox Code Playgroud)

一旦你这样做,那么SomeFunction应该是这样的:

function someFunction: TStringList;  
begin  
  Result:= TStringList.Create;  
  if someConditionIsTrue then  
    DoSomething(Result);  
  //other code  
end; 
Run Code Online (Sandbox Code Playgroud)

"字符表列表永远不会被释放"

我希望这不是设计.你创建的所有内容在某些时候都必须是免费的,特别是如果你有创建结果的函数.唯一的例外是如果你创建了一个在应用程序的整个持续时间内存在的东西,即使这样,它仍然是极端的共同点,无论如何都要释放它们.


在那个注意事项中,我在函数结果中创建对象的唯一时间是当我封装多行代码时,否则会多次重复这些代码行.例如,创建查询.

而不是重复这段代码......

Q:= TADOQuery.Create(nil);
Q.Connection:= MyDatabaseConnection;
Q.SetSomeOtherProperties;
Run Code Online (Sandbox Code Playgroud)

......我把它放在一个功能中......

function CreateQuery: TADOQuery;
begin
  Result:= TADOQuery.Create(nil);
  Result.Connection:= MyDatabaseConnection;
  Result.SetSomeOtherProperties;
end;
Run Code Online (Sandbox Code Playgroud)

然后,只要我需要重复该代码,我就可以简单地调用此函数...

Q:= CreateQuery;
Run Code Online (Sandbox Code Playgroud)


Ken*_*ssa 6

字符表列表永远不会被释放

这本身就是一个问题.就像在评论中提到的那样,会造成内存泄漏.总的来说,我对创建对象并通过结果赋予所有权的函数不屑一顾.当我需要这样做时,我通常将我的函数命名"Create*"为尽可能明确地使调用者负责释放内存.

话虽如此,一个更优雅的模式,以实现您所需要的:

procedure someFunction;  
var vStrings : TStringList;
begin  
  vStrings := TStringList.Create;  
  try
    if someConditionIsTrue then  
      doSomething(vStrings);  
    //other code  
  finally
    vStrings.Free;
  end;
end;

procedure doSomething(AStrings : TStringList);
begin
  AStrings.Add(something);
end;
Run Code Online (Sandbox Code Playgroud)

如果你真的需要你的"someFunction"来返回一个TStringList并且不希望通过参数接收一个,那么如何正确管理它以避免内存泄漏.

function CreateAndInitStrings : TStringList;  
begin  
  Result := TStringList.Create;  
  try
    if someConditionIsTrue then  
      doSomething(Result);  
    //other code  
  except
    Result.Free;
    raise;
  end;
end;
Run Code Online (Sandbox Code Playgroud)