MQL5 Il compilatore non distingue tra una classe e un puntatore ad essa - pagina 3

 
SemenTalonov:

Bingo!

SemenTalonov2019.01.10 07:36POINTER_AUTOMATICe viceversa.

Non è proprio un bingo. Per gli oggetti semplici, l'assegnazione con l'operatore = funziona. Non è sicuramente un bug.

 
SemenTalonov:

...

SemenTalonov2019.01.10 07:36POINTER_AUTOMATIC in un puntatore di tipoPOINTER_DYNAMIC e viceversa.

No. Quando non sta assegnando un puntatore automatico, sta copiando un oggetto - i valori dei suoi campi, ma solo con oggetti semplici.

 

Forum sul trading, sistemi di trading automatico e test di strategia

Il compilatore MQL5 non distingue tra una classe e un puntatore

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();
}


Da quando sono definiti (domanda agli sviluppatori)

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

e come funzionano? Il seguente codice compilato sembra delirante

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


E qui la situazione non è chiara

A* m_A[2];

void OnStart()
{
A a;

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

Non proprio un bingo. Per gli oggetti semplici, l'assegnazione con l'operatore = funziona. Non è sicuramente un bug.

Esatto, questo è il punto più importante.

Personalmente, credo che non si possa usare un operatore di assegnazione per gli oggetti se questo operatore non è esplicitamente definito, anche se gli oggetti sono semplici. Possiamo ancora in qualche modo essere d'accordo sull'assegnazione di strutture semplici. Ma le classi in cui il costruttore è necessariamente chiamato (almeno implicitamente) - possono essere assegnate solo da operatori esplicitamente definiti.

Secondo me, questo è stato fatto per rendere la vita più facile ai neofiti.

 
Georgiy Merts:

Esatto, questo è il punto principale.

Personalmente, credo che non si possa usare un operatore di assegnazione per gli oggetti se tale operatore non è esplicitamente definito, anche se gli oggetti sono semplici. Possiamo in qualche modo essere d'accordo sull'assegnazione di strutture semplici. Ma le classi in cui il costruttore è necessariamente chiamato (almeno, implicitamente) - possono essere assegnate solo con operatori esplicitamente definiti.

Secondo me, questo è stato fatto per rendere la vita più facile ai principianti.

E quelli complessi sono convenienti - senza di essi non si può restituire MqlTradeRequest, per esempio. E nelle strutture, un costruttore è anche necessariamente chiamato.

 

C'è una teoria secondo cui MQL è un C# molto spogliato. Quindi è comprensibile il comportamento del compilatore MQL in questo caso. Dopo tutto, le classi in C# sono sempre collocate nell'heap, quindi:

//+------------------------------------------------------------------+
//| 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;
}
//+------------------------------------------------------------------+

Ora occupiamoci dell'array m_A. Poiché m_A è un array di classi e le classi sono sempre collocate nell'heap, non c'è bisogno di specificare se l'array m_A è un array di puntatori o un array di oggetti stessi, perché solo la prima variante funziona sempre per le classi. Poiché m_A è sempre un array di puntatori, MQL non deve specificare se memorizza tipi di riferimento o tipi significativi. Quindi, A* m_A[2] == A m_A[2]. Amen.

 
Vasiliy Sokolov:

C'è una teoria secondo cui MQL è un C# molto spogliato. Quindi è comprensibile il comportamento del compilatore MQL in questo caso. Dopo tutto, le classi in C# sono sempre collocate nell'heap, quindi:

Ora occupiamoci dell'array m_A. Poiché m_A è un array di classi e le classi sono sempre collocate nell'heap, non c'è bisogno di specificare se l'array m_A è un array di puntatori o un array di oggetti stessi, perché solo la prima variante funziona sempre per le classi. Poiché m_A è sempre un array di puntatori, MQL non deve specificare se memorizza tipi di riferimento o tipi significativi. Quindi, A* m_A[2] == A m_A[2]. Amen.

Conclusione errata. m_A è un array di oggetti, non puntatori. E questi oggetti sono completamente distrutti. Non è il nuovo A che viene distrutto.

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:

Uscita errata. m_A è un array di oggetti, non puntatori. E questi oggetti sono completamente distrutti. Non è il nuovo A che viene distrutto.

Questo è un buon esempio. Bene, pensiamo oltre.

 

Pfft)) Sono scioccato da questo.

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)) Sono davvero scioccato da questo.

Cosa c'è che non va? In un caso un oggetto, nell'altro un puntatore.