MQL5 编译器不区分类和它的指针

 

MT5构建1940

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
class A
{
public:
    int iValue;
};
//......................
A m_A[2];

void OnStart()
{
A a;

    m_A[0] =a; 
    m_A[1] = new A();
}
//+------------------------------------------------------------------+

它在这两种情况下都能编译。

A m_A[2]; // и так

A* m_A[2]; // и так

在第一种情况下,输出是一个没有被删除的对象(新创建的)和一个内存泄漏

1 undeleted objects left
1 object of type A left
24 bytes of leaked memory

好的,手动释放......然后编译器(突然)注意到数组包含非指针:"预计是对象指针"

delete m_A[1]; // Если 'm_A' массив объектов -> object pointer expected

好的,我把它声明为一个指针数组。

A* m_A[2];

它可以编译!这对我来说是个新闻。那么,MQL到底有没有指针?因为对于像char、int等内置类型,会有

'*' - pointer cannot be used

但这次将是在运行时。

m_A[0] =a; // получаем: "invalid pointer access"

这在原则上是符合逻辑的)。

关于这个结果有一些问题。

1.如果这些子指针不能像C/C++中的指针那样发挥其主要功能,那么MQL中的这些子指针有什么用?

2.如果MT知道确切的字节数,并且可以自动释放内存,那么我们为什么要玩删除呢?

 

在删除时,你必须检查指针的类型。一个对象是用新创建的--它必须被删除(例子中的第二个),另一个是自动的(例子中的第一个),它将被自动删除。

 
Dmitry Fedoseev:

在删除时,你必须检查指针的类型。一个对象是用new创建的,它必须被删除(例子中的第二个),另一个是自动的(例子中的第一个),它将被自动删除。

也就是说,在第一种情况下,m_A[0] 将不包含堆栈对象'a'的副本 ,而是包含指向该本地对象的 某种POINTER_AUTOMATIC 类型的指针,该指针在退出函数后将成为POINTER_INVALID 类型(如果它是由另一个函数调用的)

 
那么,一般来说,问题听起来是这样的:编译器允许一个POINTER_AUTOMATIC 类型的指针被保存为一个POINTER_DYNAMIC 类型的指针,反之亦然
 
SemenTalonov:

也就是说,在第一种情况下,m_A[0] 不会是堆栈对象'a'的副本 ,而是指向该本地对象 某个POINTER_AUTOMATIC 类型的指针,该指针在退出函数后将成为POINTER_INVALID 类型(如果它是从其他函数调用的)

如果使用不当,任何东西都可能成为无效的。重点不是POINTER_INVALID,而是自动创建的对象也会被自动删除。

在任何情况下,都不能在这里创建一个对象的副本。指针只是一个指针--一个带有数字的变量,表示对象的位置,在本例中是对象 "a"。所以,你可以用 "a "来指代对象 "a",也可以用 "m_A[0]",这是一个对象,不是两个不同的对象。

原则很简单:你创造了这个对象,就自己删除它。如果你没有创造它,就不要管它。就这么简单。

 
SemenTalonov:
一般来说,问题听起来是这样的:编译器允许你将一个POINTER_DYNAMIC 类型的指针保存为一个POINTER_AUTOMATIC 类型的指针,反之亦然

反之亦然。一个POINTER_DYNAMIC 类型的指针可以分配给一个POINTER_AUTOMATIC类型 的指针。但这是正确的,也是好的--它开启了很多可能性。

 

我不明白有什么问题?

我们取一个对象数组,并将其第一个元素等同于在堆栈上创建的对象。同时,在没有声明复制操作符的情况下 !这已经是一个错误。

好吧,考虑到该对象非常简单,复制构造函数默认在那里生成。而数组包含了创建对象的 副本。

没有问题的问题。

1.指针完成了它们的作用,我个人只想念指向数组的指针。

MQL不应该删除它没有标记的东西。Dmitriy说的对,"创建一个对象,删除它"。 我不喜欢C#中 "垃圾收集器 "的做法,即对象不是在我想删除时而是在收集器想删除时被删除。

 
Georgiy Merts:

我不明白有什么问题?

我们取一个对象数组,并将其第一个元素等同于在堆栈上创建的对象。同时,在没有声明复制操作符的情况下 !这已经是一个错误。

好吧,考虑到该对象非常简单,复制构造函数默认在那里生成。而数组包含了创建对象的 副本。

这就是我所期待的副本......默认的复制构造函数不是一个错误。

但是Dmitry 说,一个新的对象将被分配到内存中,并且将返回一个POINTER_AUTOMATIC 类型的指针 不会有拷贝。

每个人都以他自己的方式理解MQL的怪癖)

 
SemenTalonov:

这就是我所期待的副本...默认的复制构造函数不是一个错误。

但是Dmitry 说,一个新的对象将被分配到内存中,并且将返回一个POINTER_AUTOMATIC 类型的指针

每个人都以他自己的方式理解MQL的怪癖)

你说它 "不是错误 "是什么意思?你正在使用一个没有定义的运算符。

好吧,你有一个几乎是空的对象,但如果这个对象中还有其他子对象,需要初始化,而这个对象本身也需要资源请求呢?

在我听来,你不能使用没有声明的东西。

"怪癖 "我没有看到,我认为Dimitri关于 "没有对象的副本 "是错误的--原因还是在于使用了一个未声明的语句。

 

一个物体的副本从何而来?指针的拷贝,是的,但指向同一个对象。

 
Georgiy Merts:

你说的 "没有错误 "是什么意思?你在使用一个没有定义的运算符。

我的观点是,一个明确声明的复制构造函数在这个测试中不会改变任何东西。

你怎么能不看到明显的...

一个指针指向一个 对象数组的一个项目,一个对象指向一个指针数组的一个项目......这真的可以吗?

在第一种情况下,数组是一个指向对象的指针,在第二种情况下,复制构造函数应该起作用,这些操作怎么可能是等同的?

原因: