gpt4 book ai didi

delphi - 将 Delphi 构造函数作为普通方法调用 - 任何隐藏的副作用?

转载 作者:行者123 更新时间:2023-12-05 08:42:28 24 4
gpt4 key购买 nike

我很困惑:为什么显式调用 Delphi 构造函数/作为普通方法不会创建新实例/为什么没有内存泄漏?

下面是一些示例代码:

TMyHelperClass = class(TObject)
private
fSomeHelperInt: integer;
public
property SomeHelperInt : integer read fSomeHelperInt write fSomeHelperInt;
constructor Create (const initSomeHelperInt : integer);
end;

TMyClass = class(TObject)
private
fHelper : TMyHelperClass;
public
constructor Create(const initSomeInt: integer);
destructor Destroy; override;
property Helper : TMyHelperClass read fHelper;
end;

实现:

constructor TMyHelperClass.Create(const initSomeHelperInt: integer);
begin
fSomeHelperInt := initSomeHelperInt;
end;

constructor TMyClass.Create(const initSomeInt: integer);
begin
fHelper := TMyHelperClass.Create(initSomeInt);
end;

destructor TMyClass.Destroy;
begin
fHelper.Free;
inherited;
end;

和用法:

var
my : TMyClass;
begin
my := TMyClass.Create(2016);
try
//WHY is this ok to be used ?
my.Helper.Create(2017);
finally
my.Free;
end;
end;

我怎么能像普通方法一样调用 TMyHelperClass+s Create 构造函数?我的意思是 - 这正是我想要的 - 但为什么没有问题(内存)?

我猜答案是因为没有像 TMyHelperClass.Create 那样调用 Create 方法(创建 TMyHelperClass 的实例)?

这种调用构造函数作为普通方法的方式是否可以接受/可以使用?

最佳答案

是的,您可以将构造函数作为普通方法调用。
但这样做是不好的做法。

why no memory leaks?

发件人:http://docwiki.embarcadero.com/RADStudio/Rio/en/Methods#Constructors

When a constructor is called using an object reference (rather than a class reference), it does not create an object. Instead, the constructor operates on the specified object, executing only the statements in the constructor's implementation, and then returns a reference to the object. A constructor is typically invoked on an object reference in conjunction with the reserved word inherited to execute an inherited constructor.

编译器在调用TObject.Create (类引用) vs AObject.Create (实例引用)时会生成不同的代码.

反模式警告
滥用构造函数作为普通方法会导致分配资源时出现问题。
通常构造函数和析构函数是匹配的,但是如果您调用构造函数两次(调用实例的构造函数时必须这样做),您将分配两次资源,但只会释放一次。

如果您想像普通方法一样调用构造函数的主体,请创建一个新方法并在构造函数中调用该方法。

例如:

constructor TTest.Create;
begin
inherited;
//Allocate needed resources here.
Init;
end;

procedure TTest.Init;
begin
//Do initialization stuff
//But don't allocate any resources

现在您可以在需要时安全地调用 init 方法,而不会出现任何意外。

可以在不“构造”任何东西的情况下调用构造函数的原因是以下代码必须有效:

constructor TTest.Create(const AObject: TObject);
begin //constructor of TTest happens here
inherited Create; //instance call to TParent.Create;
//Other code
end;

在极少数情况下,您可以完全跳过对构造函数的类调用。
以下代码将起作用:

MyTest:= TTest.NewInstance;
//Voodoo code here.
MyTest.Create;

这可用于防止编译器插入在调用 TTest.Create 时生成的自动代码。
这是很少需要的,在 20 年的编码过程中,我只用过一次。
这个用例是速度敏感代码,我想在其中避免异常检查和分配空间归零的开销,这是在 Delphi 支持带有方法的记录之前。

如果我必须再次执行该代码,我会使用一条记录并在堆上分配一个包含 1000 条记录的池,然后根据需要分发它们。

关于delphi - 将 Delphi 构造函数作为普通方法调用 - 任何隐藏的副作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41396317/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com