当前位置:  开发笔记 > 编程语言 > 正文

如何从Delphi中的函数返回一个对象而不会导致访问冲突?

如何解决《如何从Delphi中的函数返回一个对象而不会导致访问冲突?》经验,为你挑选了3个好方法。

我有一个返回TStringList的delphi函数,但是当我返回一个值并尝试使用它时,我得到一个访问冲突错误,即

myStringList := FuncStringList();
myStringList.Items.Count   // <-- This causes an access violation

// function FuncStringList
function FuncStringList:TStringList;
var
  vStrList:TStringList;
begin

  vStrList := TStringList.Create;
   ...
  // Fill the vStrList

  Result := vStrList 
  vStrList.Free;    //<- when i free here, this function will cause AccessViolation
end;

如何返回TStringList并仍然在本地函数中释放它?



1> Ken White..:

正如Smasher所说,你无法释放它; 调用返回对象的函数的代码负责销毁它.

顺便说一句,这是糟糕的代码设计,因为它使得分配和释放的人感到困惑.更好的方法是让调用者创建对象并将其传递给函数.这样,创建它的代码也可以释放它.像这样的东西:

var
  SL: TStringList;
begin
  SL := TStringList.Create;
  try
    ProcToFillStringList(SL);
    //Do something with populated list
  finally
    SL.Free;
  end;
end;

// Note I've made the parameter a TStrings and not a TStringList. This allows
// passing a TMemo.Lines or a TListBox or TComboBox Items as well.
procedure ProcToFillStringList(const SList: TStrings);
  // Do whatever populates the list with SList.Add()
end;

现在对谁做什么没有混淆 - 创建对象的相同代码负责释放它.而IMO的代码更易于阅读和维护.



2> jpfollenius..:

我如何返回TStringList并仍然在本地函数中释放它?

你不能.如果在本地函数中释放它,则无法使用返回值.结果和vStrList指向内存中的相同TStringList对象.TStringList是一个类和

Result := vStrList

因此不会复制字符串列表,而只复制引用.

所以,你应该在完成它之后释放调用上下文中的字符串列表,或者将字符串列表作为参数传递给你的函数,就像这样

procedure FuncStringList (StringList : TStringList);

让调用代码创建并释放字符串列表.正如其他答案所指出的那样,这是更好的方式,因为它使所有权非常清晰.



3> Mason Wheele..:

简单回答:你做不到.你为什么要这样做?是因为你已经知道你需要释放你在创建它们的同一个函数中创建的每个对象吗?这通常是正确的,但并非总是如此,这是规则的例外之一.更好的方法是每个对象必须由其所有者释放.

如果您有一个生成对象的函数(如此函数),但随后将其传递给另一个函数,则它不会获取该对象的所有权.删除对free的调用并对其进行记录,因此您(以及使用此函数的任何其他人)将意识到它创建了一个新对象,调用它的代码必须拥有该对象.


正是我的观点.我给像这样的函数一个以Create开头的名字,所以调用者有一个线索,他必须处理返回的对象,类似于构造函数调用的结果.
推荐阅读
虎仔球妈_459
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有