MQL5 Derleyici, bir sınıf ile ona yönelik bir işaretçi arasında ayrım yapmaz - sayfa 3

 
SemenTalonov :

Bingo!

SemenTalonov 2019.01.10 07:36 POINTER_DYNAMIC türünde bir işaretçi depolamaya izin verir ve bunun tersi de geçerlidir .

Tam olarak bingo değil. Basit nesneler için = operatörüyle atama çalışır. Kesinlikle bug değil.

 
SemenTalonov :

...

SemenTalonov 2019.01.10 07:36 POINTER_DYNAMIC türünde bir işaretçi depolamaya izin verir ve bunun tersi de geçerlidir .

Numara. Hoparlörden otomatik olduğunda, bu atanan bir işaretçi değildir, ancak bir nesne kopyalanır - alanlarının değerleri, ancak yalnızca basit nesnelerle.

 

Ticaret, otomatik ticaret sistemleri ve ticaret stratejilerinin test edilmesi hakkında forum

MQL5 Derleyici, bir sınıf ile ona yönelik bir işaretçi arasında ayrım yapmaz

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


Ne zamandan beri tanımlanmışlar (geliştiricilere soru)

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

ve nasıl çalışırlar? Aşağıdaki derlenmiş kod çılgın görünüyor

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


Ve burada durum net değil

A * m_A[ 2 ];

void OnStart ()
{
A a;

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

Tam olarak bingo değil. Basit nesneler için = operatörüyle atama çalışır. Kesinlikle bug değil.

Al işte, en önemli şey bu.

Şahsen, nesneler basit olsa bile, bu operatör açıkça tanımlanmadıkça nesneler üzerinde bir atama operatörü kullanabileceğinizi düşünmüyorum. Yine de bir şekilde basit yapıların atanması konusunda anlaşmak mümkündür. Ancak, yapıcının zorunlu olarak (en azından dolaylı olarak) çağrıldığı sınıflar, yalnızca açıkça tanımlanmış operatörler tarafından atanabilir.

Bence bu, yeni başlayanlar için hayatı kolaylaştırmak için yapıldı.

 
Georgiy Merts :

Al işte, en önemli şey bu.

Şahsen, nesneler basit olsa bile, bu operatör açıkça tanımlanmadıkça nesneler üzerinde bir atama operatörü kullanabileceğinizi düşünmüyorum. Yine de bir şekilde basit yapıların atanması konusunda anlaşmak mümkündür. Ancak, yapıcının zorunlu olarak (en azından dolaylı olarak) çağrıldığı sınıflar, yalnızca açıkça tanımlanmış operatörler tarafından atanabilir.

Bence bu, yeni başlayanlar için hayatı kolaylaştırmak için yapıldı.

Ve karmaşık olanlar uygundur - bu olmadan, örneğin MqlTradeRequest'i iade etmek imkansızdır. Ve yapılarda, yapıcı da zorunlu olarak çağrılır.

 

MQL'nin çok kırpılmış bir C# olduğu bir sürüm var. Buna dayanarak, bu durumda MQL derleyicisinin davranışı netleşir. Çünkü C#'da sınıflar her zaman öbek üzerinde tahsis edilir, yani:

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

Şimdi m_A dizisiyle ilgilenelim. m_A bir sınıflar dizisi olduğundan ve sınıflar her zaman öbek üzerinde tahsis edildiğinden, m_A dizisinin bir işaretçiler dizisi mi yoksa bir nesneler dizisi mi olduğunu belirtmeye gerek yoktur, çünkü sınıflar için yalnızca ilk seçenek her zaman çalışır. m_A her zaman bir işaretçi dizisi olduğundan, MQL'nin bir hoşgörüsü vardır: referans türlerini mi yoksa değer türlerini mi depoladığını belirtmemek mümkündür. Dolayısıyla A* m_A[2] == A m_A[2]. Amin.

 
Vasiliy Sokolov :

MQL'nin çok kırpılmış bir C# olduğu bir sürüm var. Buna dayanarak, bu durumda MQL derleyicisinin davranışı netleşir. Çünkü C#'da sınıflar her zaman öbek üzerinde tahsis edilir, yani:

Şimdi m_A dizisiyle ilgilenelim. m_A bir sınıflar dizisi olduğundan ve sınıflar her zaman öbek üzerinde tahsis edildiğinden, m_A dizisinin bir işaretçiler dizisi mi yoksa bir nesneler dizisi mi olduğunu belirtmeye gerek yoktur, çünkü sınıflar için yalnızca ilk seçenek her zaman çalışır. m_A her zaman bir işaretçi dizisi olduğundan, MQL'nin bir hoşgörüsü vardır: referans türlerini mi yoksa değer türlerini mi depoladığını belirtmemek mümkündür. Dolayısıyla A* m_A[2] == A m_A[2]. Amin.

Yanlış sonuç. m_A, işaretçiler değil, bir nesneler dizisidir. Ve bu nesneler tamamen yok edilir. Yeni A yok edilmez.

 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 :

Yanlış sonuç. m_A, işaretçiler değil, bir nesneler dizisidir. Ve bu nesneler tamamen yok edilir. Yeni A yok edilmez.

İyi örnek. hm. O zaman daha fazla düşüneceğiz.

 

haha)) Aslında buna şok oldum

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 :

haha)) Aslında buna şok oldum

Ve yanlış olan ne? Bir durumda bir nesne, diğer durumda bir işaretçi.