Mover (intercambiar) arrays
MQL5 ofrece la posibilidad de intercambiar el contenido de dos arrays de forma eficiente (sin asignación física de memoria ni copia de datos). En algunos otros lenguajes de programación, se admite una operación similar no sólo para los arrays, sino también para otras variables, y se denomina desplazamiento.
bool ArraySwap(void &array1[], void &array2[])
La función intercambia el contenido de dos arrays dinámicos del mismo tipo. Se admiten arrays de cualquier tipo. Sin embargo, la función no es aplicable a los arrays de series temporales ni a los búferes de indicadores, así como tampoco a ningún array con el modificador const.
Para arrays multidimensionales, el número de elementos de todas las dimensiones excepto la primera debe coincidir.
La función devuelve true si tiene éxito o false en caso de error.
El principal uso de la función es acelerar el programa eliminando la copia física del array cuando éste se pasa a la función o se devuelve de ella, y se sabe que el array de origen ya no es necesario. El hecho es que el intercambio se produce casi instantáneamente, ya que los datos de la aplicación no se mueven de ninguna manera. En lugar de ello hay un intercambio de metadatos sobre arrays almacenados en estructuras de servicio que describen arrays dinámicos (y esto sólo ocupa 52 bytes).
Supongamos que existe una clase destinada a procesar un array mediante determinados algoritmos. El mismo array puede ser sometido a diferentes operaciones y, por lo tanto, tiene sentido mantenerlo como un miembro de la clase. Pero entonces surge la pregunta: ¿cómo transferirlo a un objeto? En MQL5, los métodos (así como las funciones en general) permiten pasar arrays sólo por referencia. Dejando a un lado todo tipo de clases de envoltorios que contengan un array y se pasen por puntero, la única solución sencilla parece ser la siguiente: describir, por ejemplo, un parámetro de array en el constructor de la clase y copiarlo al array interno utilizando ArrayCopy. Pero es más eficaz utilizar ArraySwap.
template<typename T>
|
Dado que el array array estaba vacío antes del intercambio, después de la operación el array utilizado como argumento source quedará vacío, mientras que array se llenará con datos de entrada con poca o ninguna sobrecarga.
Una vez que el objeto de la clase se convierte en el «propietario» del array, podemos modificarlo con los algoritmos requeridos; por ejemplo, mediante un método especial process, que toma como parámetro el código del algoritmo solicitado. Puede ordenar, suavizar, mezclar, añadir ruido y mucho más. Pero antes, probemos la idea en una operación sencilla de inversión de arrays mediante la función ArrayReverse (véase el archivo ArraySwapSimple.mq5).
bool process(const int mode)
|
Puede proporcionar acceso a los resultados del trabajo utilizando dos métodos: elemento por elemento (sobrecargando el operador '[]') o por un array completo (de nuevo utilizamos ArraySwap en el método correspondiente get, pero también puede proporcionar un método para copiar a través de ArrayCopy).
T operator[](int i)
|
A efectos de universalidad, la clase se hace plantilla. Esto permitirá adaptarla en el futuro para arrays de estructuras arbitrarias, pero por ahora se puede comprobar la inversión de un array simple del tipo double:
void OnStart()
|
La tarea de ordenar es más realista, y para un array de estructuras, puede ser necesario ordenar por cualquier campo. En la sección siguiente estudiaremos en detalle la función ArraySort, que permite ordenar en orden ascendente un array de cualquier tipo integrado, pero no estructuras. Ahí intentaremos eliminar esta «laguna», dejando ArraySwap en acción.