显然,我不明白构造函数是如何工作的。
当我的应用程序启动时,它会自动或在需要时执行加载所有资源的程序 - 主要是图像。
procedure Load;
begin
AppPath := GetAppPath;
INI := TInIFile.Create(AppPath + '\Config.ini');
INI.WriteBool('Application', 'Running', True);
ResPath := AppPath + '\Resources';
Top := TPicture.Create;
TopRight := TPicture.Create;
Left := TPicture.Create;
Right := TPicture.Create;
BottomLeft := TPicture.Create;
Bottom := TPicture.Create;
BottomRight := TPicture.Create;
...
//Load the pictures ...LoadFromFile(Skin.ReadString('Skin', ..., ...));
当我使用这个应用程序时,它开始有点滞后,但操作系统开始冻结和滞后。当我在任务管理器中看到我的程序时,我感到很震惊:
如果我是对的,应用程序使用600兆内存,包含页面文件。我的系统只有1 GB的RAM,因此难怪操作系统和几乎所有程序都因页面文件的使用而开始滞后。
原来这是我每次做某事时加载资源的相同程序。我通过向单元添加布尔值来修复它,并且当它被设置为true时取消了该过程(意味着加载了资源)。
Loaded: Boolean;
...
if Loaded = False then Load;
我不明白为什么我必须做出改变。为什么构造函数首先为已经创建的对象分配内存?
答案 0 :(得分:11)
构造函数仅在对象尚不存在时分配内存。如果在现有对象上调用构造函数,则构造该对象;没有分配新的。 (你决定在里面构造函数是另一回事。除了InstanceSize
函数为类返回的内容之外,这些指令可能会分配更多的内存。)
但是,您的代码不会显示在现有对象上调用的任何构造函数。您正在 classes 上调用构造函数,并为每个类分配一个新实例。例如,您构造一个INI文件对象:
INI := TInIFile.Create(AppPath + '\Config.ini');
调用TIniFile
上的构造函数。它分配一个新的TIniFile
实例并初始化它。完成后,对该新对象的引用将存储在INI
变量中。需要注意的是,如果INI
已经拥有对某些其他对象的引用,则该引用将被丢弃,而新引用将存储在INI
中。您没有在已TIniFile
引用的对象上调用INI
构造函数。该对象完全独立于正在创建的新对象。
INI
变量不是TIniFile
对象。它是对象的引用。
您显然多次调用Load
函数。每次调用它时,都会重新运行之前运行的所有对象构造函数。您有内存泄漏,因为每次构造一组新对象时,都会在已存储前一个对象引用的相同变量中存储对它们的引用。之前的值被丢弃,并且无法将它们恢复,所以没有办法解放他们。解决这个问题的方法如下所示:确保只通过跟踪是否已经加载来初始化程序。