gpt4 book ai didi

delphi - 如果未调用 TPngImage.Free(),则当 TPngImage 超出范围时,是否调用 TPngImage.Destroy()

转载 作者:行者123 更新时间:2023-12-03 15:49:29 26 4
gpt4 key购买 nike

我有一个函数,它接受 TPicture 作为参数并返回 TPngImage。为了保留原始图像,我创建了一个 TPngImage 并将 TPicture 复制到 TPngImage,应用效果并返回 TPngImage。就这样。

function Effect( const Value : TPicture ) : TPngImage;
var
AnImage : TPngImage;

begin
if( Value.Graphic is TPngImage ) then
begin
AnImage := TPngImage.Create();
AnImage.Assign( TPngImage( Value ) );
//Apply effect
Result := AnImage;
//AnImage.Free(); //error
end;
end;

procedure TForm11.Button1Click( Sender : TObject );
begin
Image2.Picture.Assign( Effect( Image1.Picture ) );
end;

当我创建一个对象时,什么时候释放创建的对象。我无法在函数中调用 TPngImage.Free() ,因为它会在赋值之前销毁对象。那么如何释放创建的对象呢?当对象超出范围时,TPngImage 是否调用其析构函数?据我所知,不释放对象会导致内存泄漏。

最佳答案

您的代码中有几个错误:

if( Value.Graphic is TPngImage ) then

如果调用者的 TPicture 尚未包含 TPNGImage,则根本不会返回任何内容。 结果未定义。

事实上,您根本不应该检查Graphic的类型。各种 TGraphic 类可以相互分配,将它们的图像数据从一种格式转换为另一种格式,因此您应该尽可能让这种转换发生。

AnImage.Assign( TPngImage( Value ) );

您正在对 TPicture 本身进行类型转换。您需要对其 Graphic 进行类型转换。

Result := AnImage;
//AnImage.Free();

这要求调用者获得 TPNGImage 的所有权并释放它,这通常是一个糟糕的设计。

Image2.Picture.Assign( Effect( Image1.Picture ) );

举个例子,调用者没有获得返回的 TPngImage 的所有权,因此它被泄露。

如果您想返回新的 TPNGImage,请尝试以下操作:

function Effect(Value : TPicture) : TPngImage;
begin
Result := TPngImage.Create;
try
if (Value.Graphic <> nil) and (not Value.Graphic.Empty) then
begin
Result.Assign(Value.Graphic);
//Apply effect
end;
except
Result.Free;
raise;
end;
end;

或者

function Effect(Value : TPicture) : TPngImage;
begin
Result := nil;
if (Value.Graphic <> nil) and (not Value.Graphic.Empty) then
begin
Result := TPngImage.Create;
try
Result.Assign(Value.Graphic);
//Apply effect
except
Result.Free;
raise;
end;
end;
end;

无论哪种方式,您都可以执行以下操作:

procedure TForm11.Button1Click(Sender : TObject);
var
AImage: TPngImage;
begin
AImage := Effect(Image1.Picture);
try
Image2.Picture.Assign(AImage);
finally
AImage.Free;
end;
end;

但是,更好的设计是根本不返回新的 TPngImage。传入 2 个 TPicture 对象并让 Effect() 根据需要操作它们:

procedure Effect(Input, Output : TPicture);
var
AnImage : TPngImage;
begin
AnImage := TPngImage.Create;
try
if (Input.Graphic <> nil) and (not Input.Graphic.Empty) then
begin
AnImage.Assign(Input.Graphic);
//Apply effect
end;
Output.Assign(AnImage);
finally
AnImage.Free;
end;
end;

或者

procedure Effect(Input, Output : TPicture);
var
AnImage : TPngImage;
begin
if (Input.Graphic <> nil) and (not Input.Graphic.Empty) then
begin
AnImage := TPngImage.Create.Create;
try
AnImage.Assign(Input.Graphic);
//Apply effect
Output.Assign(AnImage);
finally
AnImage.Free;
end;
end else
Output.Assign(nil);
end;

然后你可以这样做:

procedure TForm11.Button1Click(Sender : TObject);
begin
Effect(Image1.Picture, Image2.Picture);
end;

关于delphi - 如果未调用 TPngImage.Free(),则当 TPngImage 超出范围时,是否调用 TPngImage.Destroy(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52568296/

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