Перемещение (обмен) массивов
MQL5 позволяет экономным образом (без физического выделения памяти и копирования данных) обменивать содержимое двух массивов между собой. В некоторых других языках программирования похожая операция поддерживается не только для массивов, но и других переменных, и называется перемещением (move).
bool ArraySwap(void &array1[], void &array2[])
Функция обменивает между собой содержимое двух динамических массивов одного типа. Поддерживаются массивы любых типов. Однако функция неприменима к массивам таймсерий и буферам индикаторов, а также любым массивам с модификатором const.
Для многомерных массивов количество элементов во всех измерениях кроме первого должно совпадать.
Функция возвращает true в случае успеха или false в случае ошибки.
Основная область применения функции — ускорение работы программы за счет исключения физического копирования массива, когда он передается в функцию или возвращается из неё, причем известно, что массив-источник больше не потребуется. Дело в том, что обмен происходит практически моментально, за счет того, что прикладные данные никоим образом не перемещаются. Вместо этого происходит обмен мета-данными о массивах, хранящихся в служебных структурах, описывающих динамические массивы (а это всего лишь 52 байта).
Представим себе некий класс, предназначенный для обработки массива определенными алгоритмами. Один и тот же массив может быть подвергнут разным операциям и потому его имеет смысл сохранить в качестве члена класса. Но встает вопрос, как его передать в объект? Методы (как и вообще функции) в MQL5 позволяют передавать массивы только по ссылке. Если отставить в сторону всевозможные классы-обертки, содержащие массив и передаваемые по указателю, единственным простым решением кажется следующее: описать, например, в конструкторе класса массив-параметр и копировать его во внутренний массив с помощью ArrayCopy. Но более эффективным является как раз использование ArraySwap.
template<typename T>
|
Поскольку массив array до обмена был пустым, после операции пустым станет массив, использованный в качестве аргумента source. Зато array окажется заполненным входными данными практически без накладных расходов.
После того как "владельцем" массива становится объект класса, мы можем его модифицировать требуемыми алгоритмами, предположим через специальный метод process, который принимает в качестве параметра код запрашиваемого алгоритма. Это может быть сортировка, сглаживание, перемешивание, добавление шума и многое другое. Но для начала попробуем проверить идею на простой операции разворота массива функцией ArrayReverse (см. файл ArraySwapSimple.mq5).
bool process(const int mode)
|
Предоставить доступ к результатам работы можно с помощью двух методов: поэлементно (перегрузив оператор '[]') или целиком массивом (в соответствующем методе get опять используем ArraySwap, но можно предусмотреть и метод копирования через ArrayCopy).
T operator[](int i)
|
С целью универсальности класс сделан шаблонным. Это позволит адаптировать его в перспективе для массивов произвольных структур, а пока можно проверить обращение простого массива типа double:
void OnStart()
|
Более приближенной к реальности является задача сортировки, причем для массива структур может потребоваться сортировка по любому полю. В следующем разделе мы досконально изучим функцию ArraySort, которая позволяет сортировать по возрастанию массив любого встроенного типа, но не структур. Там мы и попробуем ликвидировать этот "пробел", оставив в действии ArraySwap.