Di chuyển (hoán đổi) mảng
MQL5 cung cấp khả năng hoán đổi nội dung của hai mảng một cách hiệu quả về tài nguyên (mà không cần phân bổ bộ nhớ vật lý và sao chép dữ liệu). Trong một số ngôn ngữ lập trình khác, thao tác tương tự được hỗ trợ không chỉ cho mảng mà còn cho các biến khác, và được gọi là di chuyển.
bool ArraySwap(void &array1[], void &array2[])
Hàm này hoán đổi nội dung của hai mảng động cùng loại. Mọi loại mảng đều được hỗ trợ. Tuy nhiên, hàm không áp dụng được cho mảng chuỗi thời gian và bộ đệm chỉ báo, cũng như bất kỳ mảng nào có sửa đổi const
.
Đối với mảng đa chiều, số lượng phần tử ở tất cả các chiều trừ chiều đầu tiên phải khớp nhau.
Hàm trả về true
nếu thành công hoặc false
nếu xảy ra lỗi.
Công dụng chính của hàm là tăng tốc độ chương trình bằng cách loại bỏ việc sao chép vật lý của mảng khi nó được truyền vào hoặc trả về từ hàm, và khi biết rằng mảng nguồn không còn cần thiết nữa. Thực tế là việc hoán đổi diễn ra gần như ngay lập tức vì dữ liệu ứng dụng không di chuyển theo bất kỳ cách nào. Thay vào đó, có một sự trao đổi siêu dữ liệu về mảng được lưu trữ trong các cấu trúc dịch vụ mô tả mảng động (và điều này chỉ chiếm 52 byte).
Giả sử có một lớp được thiết kế để xử lý một mảng bằng các thuật toán nhất định. Cùng một mảng có thể được áp dụng cho các thao tác khác nhau và do đó, việc giữ nó như một thành viên của lớp là hợp lý. Nhưng sau đó, câu hỏi đặt ra là làm thế nào để truyền nó vào một đối tượng? Trong MQL5, các phương thức (cũng như các hàm nói chung) chỉ cho phép truyền mảng bằng tham chiếu. Bỏ qua tất cả các loại lớp bao bọc chứa mảng và được truyền bằng con trỏ, giải pháp đơn giản duy nhất dường như là: mô tả, ví dụ, một tham số mảng trong hàm khởi tạo của lớp và sao chép nó vào mảng nội bộ bằng ArrayCopy
. Nhưng việc sử dụng ArraySwap
sẽ hiệu quả hơn.
template<typename T>
class Worker
{
T array[];
public:
Worker(T &source[])
{
// ArrayCopy(array, source); // tiêu tốn bộ nhớ và thời gian
ArraySwap(source, array);
}
...
};
2
3
4
5
6
7
8
9
10
11
12
13
Vì mảng array
trống trước khi hoán đổi, sau thao tác, mảng được sử dụng làm tham số source
sẽ trở thành trống, trong khi array
sẽ được điền dữ liệu đầu vào với rất ít hoặc không có chi phí.
Sau khi đối tượng của lớp trở thành "chủ sở hữu" của mảng, chúng ta có thể sửa đổi nó bằng các thuật toán cần thiết, ví dụ, thông qua một phương thức đặc biệt process
, phương thức này nhận mã của thuật toán được yêu cầu làm tham số. Nó có thể là sắp xếp, làm mịn, trộn lẫn, thêm nhiễu và nhiều thứ khác. Nhưng trước tiên, hãy thử kiểm tra ý tưởng này trên một thao tác đơn giản là đảo ngược mảng bằng hàm ArrayReverse
(xem tệp ArraySwapSimple.mq5
).
bool process(const int mode)
{
if(ArraySize(array) == 0) return false;
switch(mode)
{
case -4:
// ví dụ: xáo trộn
break;
case -3:
// ví dụ: logarithm
break;
case -2:
// ví dụ: thêm nhiễu
break;
case -1:
ArrayReverse(array);
break;
...
}
return true;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Bạn có thể cung cấp quyền truy cập vào kết quả công việc bằng hai phương pháp: từng phần tử (bằng cách nạp chồng toán tử []
) hoặc toàn bộ mảng (một lần nữa chúng ta sử dụng ArraySwap
trong phương thức tương ứng get
, nhưng bạn cũng có thể cung cấp một phương thức để sao chép thông qua ArrayCopy
).
T operator[](int i)
{
return array[i];
}
void get(T &result[])
{
ArraySwap(array, result);
}
2
3
4
5
6
7
8
9
Để đảm bảo tính phổ quát, lớp được tạo dưới dạng mẫu. Điều này sẽ cho phép điều chỉnh nó trong tương lai cho các mảng của các cấu trúc tùy ý, nhưng hiện tại, bạn có thể kiểm tra việc đảo ngược một mảng đơn giản của loại double
:
void OnStart()
{
double data[];
ArrayResize(data, 3);
data[0] = 1;
data[1] = 2;
data[2] = 3;
PRT(ArraySize(data)); // 3
Worker<double> simple(data);
PRT(ArraySize(data)); // 0
simple.process(-1); // đảo ngược mảng
double res[];
simple.get(res);
ArrayPrint(res); // 3.00000 2.00000 1.00000
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Nhiệm vụ sắp xếp thực tế hơn, và đối với mảng của các cấu trúc, có thể cần sắp xếp theo bất kỳ trường nào. Trong phần tiếp theo, chúng ta sẽ nghiên cứu chi tiết hàm ArraySort
, hàm này cho phép sắp xếp theo thứ tự tăng dần một mảng của bất kỳ loại tích hợp nào, nhưng không phải cấu trúc. Ở đó, chúng ta sẽ cố gắng loại bỏ "khoảng trống" này, vẫn giữ ArraySwap
hoạt động.