Особенности языка mql5, тонкости и приёмы работы - страница 309

 
Небольшой пример, показывающий изменения в MQL5 после b5200.

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Новая версия платформы MetaTrader 5 build 5200: расширение OpenBLAS и усиление контроля в MQL5

Ilyas, 2025.08.04 14:08

Для однозначности, операция 'TYPE NAME = INITIALIZER', больше не будет разбиваться на две операции DECL + ASSIGNMENT, а останется одной 'DECL [has initializer]'
Если требуется объявить переменную и вызвать для неё оператор =, разбивайте операцию на две части вручную: DECL; ASSIGNMENT; (да, с констаностью переменной придётся расстаться)

struct A
{
  int Tmp;

//  A() {}
//  A( const A& ) { Print(__FUNCSIG__); } 
  
  void operator =( const A& ) { Print(__FUNCSIG__); }
};

void OnStart () 
{ 
  A a1;
  
  // const - допускается.
  /*const */ A a2 = a1;     // Вызывается неявный конструктор копирования A::A(const A&)
  
  // const - не допускается.
  /*const */ A a3; a3 = a1; // Вызывается оператор копирования A::operator=(const A&)
}


Аналогично.

class B
{
  A a;

public:  
  B( const A &Tmp) : a(Tmp) // Вызывается неявный конструктор копирования A::A(const A&)
  {
    a = Tmp;                // Вызывается оператор копирования A::operator=(const A&)
  }
};

void OnStart()
{
  A a;
  B b(a);
}


Если возникает необходимость инициализировать статический объект через оператор копирования, то это возможно сделать таким приемом.

class B
{
  static A a1;
  static A a2;
  static A a3;
  
  static bool Init;
  
  template <typename T>
  static bool Operator( T &Dest, const T& Source )
  {
    Dest = Source; // Вызывается оператор копирования T::operator=(const T&)
    
    return(true);
  }
};

static A B::a1;
static A B::a2; // Нужно B::a2 = B::a1 через A::operator=(const A&)
static A B::a3; // Нужно B::a3 = B::a1 через A::operator=(const A&)

static bool B::Init = B::Operator(B::a2, B::a1) && // B::a2 = B::a1 через A::operator=(const A&)
                      B::Operator(B::a3, B::a1);   // B::a3 = B::a1 через A::operator=(const A&)
 
Обратите внимание на такие конструкции в своих исходниках. После b5200 они могут прекратить работать, как раньше. При этом компилятор ничего не сообщит об этом.
 
Появление неявного конструктора копирования позволяет делать такие записи.
void OnStart()
{
  MqlTick Tick;
  
  // Два разных способа вызвать MqlTick::MqlTick(const MqlTick&)
  const MqlTick Tick1 = Tick;
  const MqlTick Tick2(Tick); // b5200-: function not defined, b5200+: OK.
}
 
fxsaber #:
Появление неявного конструктора копирования позволяет делать такие записи.
class A {};

A Func()
{
  A a;
  
  return(a); // b5200-: object of 'class A' cannot be returned, copy constructor 'A::A(const A &)' not found, b5200+: OK.
};

Однако, использование такой возможности теряет совместимость с MQL4.

 
fxsaber #:
Обратите внимание на такие конструкции в своих исходниках. После b5200 они могут прекратить работать, как раньше. При этом компилятор ничего не сообщит об этом.

Пример такой опасности разного выполнения ДО и ПОСЛЕ b5200.

struct A
{
  int Tmp;
  
  void operator =( const A&) { Print(__FUNCSIG__); }
  
  A f()
  {
    return(this); // Возврат объекта.
  }
};

void OnStart()
{
  A a;
  
  a.f(); // b5200-: void A::operator=(const A&), b5200+: NULL.
}

Поэтому внимательно смотрите функции, где идет возврат объекта.

 

Недокументированная константа:

MQL_GLOBAL_COUNTER

  • Возвращает уникальное значение счетчика, которое увеличивается каждый раз, когда любая MQL-программа (советник, скрипт, индикатор) вызывает MQLInfoInteger(MQL_GLOBAL_COUNTER).

  • Считайте, что это монотонно увеличивающийся глобальный счетчик запусков во всей сессии терминала MetaTrader, а не только в рамках одного эксперта или графика.

  • Счетчик начинается с 1 при запуске терминала и увеличивается каждый раз, когда новый экземпляр MQL-программы вызывает MQLInfoInteger( MQL_GLOBAL_COUNTER).

  • Период счетчика представляет собой 32-битное знаковое целое число в диапазоне [1, 2147483647].

Примеры использования

  • Засеивание ГПСЧ значением, которое отличается для каждого запуска программы (чтобы избежать одинаковых последовательностей при одновременном запуске нескольких советников/скриптов).

  • Создание уникальных идентификаторов для всех скриптов/ЭА без риска коллизии.

Пример

void OnStart()
{
   Print("Global counter = ", MQLInfoInteger(MQL_GLOBAL_COUNTER));
}

Если вы запустите этот скрипт несколько раз, вы увидите растущие числа, например:

Global counter = 25
Global counter = 26
Global counter = 27

Важно:

  • Это глобальное значение для терминальной сессии, оно не сбрасывается для каждого графика или эксперта.

  • Как только вы перезапустите MetaTrader, счетчик вернется к 1.

Короче говоря:
MQLInfoInteger(MQL_GLOBAL_COUNTER) дает вам уникальное, увеличивающееся целое число каждый раз, когда MQL-программа вызывает функцию MQLInfoInteger .

(Как это было обнаружено: см. https://www. mql5.com/en/code/56055)

 
amrali #:

Недокументированная константа:

MQL_GLOBAL_COUNTER

Спасибо за информацию!

 
amrali #:

MQL_GLOBAL_COUNTER

Спасибо за информацию!

Интересно, реализован ли атомарный доступ к этому счетчику. Если 2 или больше индикаторов работают на одном инструменте, получат ли они разные цифры?

 
Andrey Khatimlianskii #:
Если 2 или больше индикаторов работают на одном инструменте, получат ли они разные цифры?

Разные. На график прикреплены 2 индикатора Buttons, у первого сверху уникальный ID "Buttons01", у второго "Buttons02".

2025.08.29 12:59:36.819 Buttons (GBPCAD,H2)     Global counter Buttons02 = 50
2025.08.29 12:59:36.831 Buttons (GBPCAD,H2)     Global counter Buttons01 = 51
2025.08.29 13:00:35.086 Buttons (GBPCAD,H1)     Global counter Buttons02 = 52
2025.08.29 13:00:35.113 Buttons (GBPCAD,H1)     Global counter Buttons01 = 53
 
Andrey Khatimlianskii #:

Спасибо за информацию!

Интересно, а реализован ли атомарный доступ к этому счетчику? Если 2 или более индикатора работают на одном инструменте, будут ли они получать разные числа?

Индикаторы для данного инструмента работают в одном потоке, поэтому они выполняются последовательно, а не параллельно.