Creating and Deleting Objects
对象的创建与删除
当MQL4程序加载并执行后,内存会根据变量的类型分配给每个变量。根据访问级别,所有变量分为两种类型——全局变量和局部变量。根据内存类别,它们可以是MQL4程序的输入参数、静态变量或自动变量。如果需要,每个变量都会通过相应的值进行初始化。使用后,变量会被取消初始化,其占用的内存将返回给MQL4可执行系统。
全局变量的初始化与取消初始化
全局变量在MQL4程序加载后立即且在任何函数调用之前自动初始化。在初始化过程中,简单类型类型的变量会分配初始值,对象也会调用构造函数(如果有的话)。输入变量始终在全局级别声明,并通过用户在程序启动时设置的对话框中的值进行初始化。
尽管静态变量通常声明在局部级别,但这些变量的内存是预先分配的,初始化在程序加载后立即进行,与全局变量的初始化顺序相同。
初始化顺序与程序中变量的声明顺序一致。取消初始化则按相反的顺序进行。这一规则仅适用于不是通过new运算符创建的变量。这些变量在加载后自动创建并初始化,然后在程序卸载前取消初始化。
局部变量的初始化与取消初始化
如果在局部级别声明的变量不是静态变量,则会自动为该变量分配内存。局部变量和全局变量在程序执行遇到其声明时自动初始化。因此,初始化顺序与声明顺序一致。
局部变量在其声明所在的程序块结束时取消初始化,且顺序与声明顺序相反。程序块是复合运算符的一部分,可以是选择运算符switch、循环运算符(for、while、do-while)、函数体或if-else运算符的一部分。
局部变量仅在程序执行遇到变量声明时初始化。如果变量声明的代码块在程序执行过程中未被执行,则该变量不会初始化。
放置对象的初始化与取消初始化
特殊情况是对象指针,因为指针的声明并不涉及相应对象的初始化。动态放置的对象仅在通过new运算符创建类实例时初始化。对象的初始化需要调用相应类的构造函数。如果类中没有相应的构造函数,其简单类型的成员将不会自动初始化;字符串、动态数组和复杂对象类型的成员将自动初始化。
指针可以在局部或全局级别声明;它们可以通过NULL的空值或相同类型或继承类型的指针值进行初始化。如果为在局部级别声明的指针调用new运算符,则必须在离开该级别之前执行delete运算符。否则,指针将丢失,对象的显式删除将失败。
所有通过object_pointer=new Class_name表达式创建的对象都必须通过delete(object_pointer)运算符删除。如果由于某些原因,在程序结束时没有使用delete运算符删除此类变量,则相应的条目将出现在“专家”日志中。可以声明多个变量,并将一个对象的指针分配给所有变量。
如果动态创建的对象有构造函数,则在new运算符执行时调用该构造函数。如果对象有析构函数,则在delete运算符执行时调用。
因此,动态放置的对象仅在调用相应的new运算符时创建,并且必须通过delete运算符或在程序卸载过程中由MQL4执行系统自动删除。动态创建对象的指针的声明顺序不影响其初始化顺序。初始化和取消初始化的顺序完全由程序员控制。
MQL4中的动态内存分配
在处理动态数组时,释放的内存会立即返回给操作系统。
使用new运算符处理动态类对象时,首先从内存管理器工作的类内存池请求内存。如果池中内存不足,则从操作系统请求内存。使用delete运算符删除动态对象时,释放的内存会立即返回到类内存池。
内存管理器在以下事件处理函数退出后立即将内存返回给操作系统:OnInit()、OnDeinit()、OnStart()、OnTick()、OnCalculate()、OnTimer()、OnTester()、OnChartEvent()。
变量的简要特性
关于创建、删除、构造函数和析构函数调用的主要信息如下表所示。
| 全局自动变量 | 局部自动变量 | 动态创建的对象 | |
|---|---|---|---|
| 初始化 | mql4程序加载后 | 在代码行声明时执行 | new运算符执行时 |
| 初始化顺序 | 按声明顺序 | 按声明顺序 | 与声明顺序无关 |
| 取消初始化 | mql4程序卸载前 | 当退出声明块时 | 执行delete运算符或mql4程序卸载前 |
| 取消初始化顺序 | 与初始化顺序相反 | 与初始化顺序相反 | 与初始化顺序无关 |
| 构造函数调用 | mql4程序加载时 | 初始化时 | new运算符执行时 |
| 析构函数调用 | mql4程序卸载时 | 当退出变量初始化的块时 | 执行delete运算符时 |
| 错误日志 | “专家”日志中记录关于尝试删除自动创建对象的消息 | “专家”日志中记录关于尝试删除自动创建对象的消息 | 在mql4程序卸载时记录关于未删除动态创建对象的消息 |