MQL5 O compilador não faz distinção entre uma classe e um ponteiro para ela - página 3

 
SemenTalonov:

Bingo!

SemenTalonov2019.01.10 07:36ponteiro tipoPOINTER_AUTOMÁTICOe vice versa.

Não é bem um bingo. Para a atribuição de objetos simples com operador = funciona. Não é um bug, com certeza.

 
SemenTalonov:

...

SemenTalonov2019.01.10 07:36POINTER_AUTOMÁTICO para um ponteiro do tipoPOINTER_DYNAMIC e vice versa.

Não. Quando não está atribuindo um ponteiro ao automático, está copiando um objeto - os valores de seus campos, mas somente com objetos simples.

 

Fórum sobre comércio, sistemas automatizados de comércio e testes estratégicos

O Compilador MQL5 não faz distinção entre uma classe e um ponteiro

SemenTalonov, 2019.01.10 04:18

class A
{
public:
    int iValue;
};
//......................
A m_A[2];

void OnStart()
{
A a;

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


Desde quando eles são definidos (pergunta aos desenvolvedores)

void A::operator =( const A& );
void A::operator =( const A* );

E como eles funcionam? O seguinte código compilado parece ilusório

    A* b = NULL;    
    m_A[1] = b;    


E aqui a situação não é clara

A* m_A[2];

void OnStart()
{
A a;

    m_A[0] =a;  // Почему это работает?
    m_A[0] =&a; // Когда должно работать только это?
}
 
Dmitry Fedoseev:

Não é exatamente um bingo. Para objetos simples, a atribuição com operador = funciona. Não é um bug, com certeza.

Isso mesmo, esse é o ponto mais importante.

Pessoalmente, acredito que não se pode usar um operador de atribuição para objetos se este operador não estiver explicitamente definido, mesmo que os objetos sejam simples. Ainda podemos, de alguma forma, concordar sobre a atribuição de estruturas simples. Mas as classes nas quais o construtor é necessariamente chamado (pelo menos implicitamente) - só podem ser atribuídas por operadores explicitamente definidos.

Na minha opinião, isto foi feito para facilitar a vida dos novatos.

 
Georgiy Merts:

É isso mesmo, esse é o ponto principal.

Pessoalmente, acredito que não se pode usar um operador de atribuição para objetos se esse operador não estiver explicitamente definido, mesmo que os objetos sejam simples. Podemos, de alguma forma, concordar com a atribuição de estruturas simples. Mas as classes onde o construtor é necessariamente chamado (pelo menos, implicitamente) - só podem ser atribuídas com operadores explicitamente definidos.

Na minha opinião, isto foi feito para facilitar a vida dos iniciantes.

E os complexos são convenientes - sem ele não é possível devolver o MqlTradeRequest, por exemplo. E nas estruturas, um construtor também é necessariamente chamado de construtor.

 

Há uma teoria de que a MQL é um C# muito despojado. Portanto, é compreensível como o compilador MQL se comporta neste caso. Afinal, as classes em C# são sempre colocadas na pilha, portanto:

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

void OnStart()
{
    // Разместили A в куче, указатель на A передали в m_A[1]
    m_A[1] = new A();
    // Разместили A на стеке...
    A a;
    // А вот фиг вам! ля-ля-ля;) Там вам не тут. 'a' - класс и размещается в куче. Указатель на него передается внутреннему сборщику мусора
    // А раз так, то теперь он AUTOMATIC и к нему нельзя применить delete, т.к. внутренний сборщик мусора его удалит сам 
    
    // скопировали указатель a в массив
    m_A[0] = a;
}
//+------------------------------------------------------------------+

Agora vamos lidar com a matriz m_A. Como m_A é uma matriz de classes e as classes são sempre colocadas na pilha, não há necessidade de especificar se a matriz m_A é uma matriz de ponteiros ou uma matriz dos próprios objetos, porque apenas a primeira variante sempre funciona para as classes. Como o m_A é sempre um conjunto de indicadores, a MQL não precisa especificar se armazena tipos de referência ou tipos significativos. Portanto, A* m_A[2] == A m_A[2]. Amém.

 
Vasiliy Sokolov:

Há uma teoria de que a MQL é um C# muito despojado. Portanto, é compreensível como o compilador MQL se comporta neste caso. Afinal, as aulas em C# são sempre colocadas na pilha, portanto:

Agora vamos lidar com a matriz m_A. Como m_A é uma matriz de classes e as classes são sempre colocadas na pilha, não há necessidade de especificar se a matriz m_A é uma matriz de ponteiros ou uma matriz dos próprios objetos, porque apenas a primeira variante sempre funciona para as classes. Como o m_A é sempre um conjunto de indicadores, a MQL não precisa especificar se armazena tipos de referência ou tipos significativos. Portanto, A* m_A[2] == A m_A[2]. Amém.

Conclusão incorreta. m_A é um conjunto de objetos, não de ponteiros. E estes objetos são completamente destruídos. Não é o novo A que é destruído.

class A
{
public:
    int iValue;
    
  ~A()
  {
    Print(__FUNCSIG__);
  }
};
//......................
A m_A[2];

void OnStart()
{
A a;
A* b = new A;

    m_A[0] =a;  // копирование объекта, а не указателя
    m_A[1] = b; // копирование объекта, а не указателя
    
  // по выходу уничтожится три объекта
  delete b; // а так - четыре.
}
 
fxsaber:

Saída incorreta. m_A é um conjunto de objetos, não de ponteiros. E estes objetos são completamente destruídos. Não é o novo A que é destruído.

Esse é um bom exemplo. Bem, passemos então a pensar sobre isso.

 

Pfft)) Estou chocado com isto.

A m_A[2];

void OnStart()
{
A a;
A* b = new A();

    printf("SizeOf 'a' object: %i SizeOf pointer 'b' to object: %i", sizeof(a), sizeof(b));
    
    a =b;
    b =a;
    
    m_A[0] = a;
    m_A[1] = b;
}
SizeOf 'a' object: 20 SizeOf pointer to 'b' object: 8
 
SemenTalonov:

Phew)) Estou realmente chocado com isto.

O que há de errado com isso? Num caso, um objeto, no outro, um ponteiro.