Функция ArrayResize, пара вопросов.

 

Всем привет.

В обновлённой версии языка для 4 версии увидел, что добавилась новая переменная в этой функции: // резервное значение размера (избыточное).

По работе скрипта понял, что работает действительно быстрее, но почему и как - не понял. 

Вот кусок кода из примера в документации:

 Вторая строчка - это уже присвоение массиву размера сразу в 100 000 элементов, а потом в цикле уже опять установление размера = i  ?

 

   double arr[];
   ArrayResize(arr,100000,100000);
//--- проверим, как быстро работает вариант с резервированием памяти 
   Print("--- Test Fast: ArrayResize(arr,100000,100000)");
   for(int i=1;i<=600000;i++)
     {
      //--- задаем новый размер массива с указанием резерва в 100000 элементов!
      ArrayResize(arr,i,100000);
      //--- при достижении круглой цифры выводим размер массива и затраченное время
      if(ArraySize(arr)%100000==0)
        {
         now=GetTickCount();
         count++;
         PrintFormat("%d. ArraySize(arr)=%d Time=%d ms",count,ArraySize(arr),(now-start));
         start=now; 
        }
     }

 Если вторую строчку представить как 

ArrayResize(arr,1,100000);

Это будет правильно или нет? 

 

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

Допустим, я не знаю, до какого размера у меня вырастет массив, знаю ориентировочно, что , допустим, до 1 млн. И расти он будет поэлементно: появилось новое значение - увеличиваем массив на 1, заносим значение. Какое значение лучше поставить в этом случае для резервного значения размера? 1 000, 10 000,  100 000, 1 000 000  ?  Как от этого будет меняться скорость работы?

Как правильно писать код: в инициализации указать  

ArrayResize(arr,100000,100000);

и потом уже в теле советника менять размер массива от 1 до 1млн?

 ArrayResize(arr,1,100000);

ArrayResize(arr,1 000 000,100000); 

 

Или какие-то другие варианты?

 

И ещё вопрос. Если я вначале , допустим, в инициализации использую этот третий параметр, указываю резервное значение массива, а потом в теле советника не использую нигде - резервирования памяти происходить не будет? 

 

Спасибо за ответы. 

 
А что, так это никто и не знает?
 
Alexander #:
А что, так это никто и не знает?
В документации же всё понятно расписано:

При частом распределении памяти рекомендуется использовать третий параметр, задающий резерв для уменьшения количества физического распределения памяти. Все последующие вызовы функции ArrayResize не приводят к физическому перераспределению памяти, а только меняется размер первого измерения массива в пределах зарезервированной памяти. Следует помнить, что третий параметр будет использоваться только тогда, когда будет происходить физическое распределение памяти, например:

ArrayResize(arr,1000,1000);
for(int i=1;i<3000;i++)
   ArrayResize(arr,i,1000);

В данном случае произойдёт 2 перераспределения памяти, один раз до входа в цикл на 3000 итераций, при этом размерность массива будет установлена в 1000 и второй при i равной 2000. Если третий параметр опустить, то произойдёт 2000 физических перераспределения памяти и это замедлит выполнение программы.

 
Но в вызове
ArrayResize(arr,1000,1000) я не вижу никакого смысла, т.к. он идентичен вызову ArrayResize(arr,1000)
 
Sergey Gridnev #:
Но в вызове
ArrayResize(arr,1000,1000) я не вижу никакого смысла, т.к. он идентичен вызову ArrayResize(arr,1000)

Не совсем идентичен

#define SIZE 1000000

void f(int newSize, int reserve)
  {
   double arr[];
   ArrayResize(arr, newSize, reserve);
   Print("MQL_MEMORY_USED ", MQLInfoInteger(MQL_MEMORY_USED));
  }
void OnStart()
  {
   f(SIZE, 0); // MQL_MEMORY_USED 8
  }
void OnStart()
  {
   f(SIZE, SIZE); // MQL_MEMORY_USED 16
  }
 

Здравствуйте, Павел.

Третий параметр функции ArrayResize() задаёт не сколько, а на сколько больше от запрошенного размера будет сразу выделено памяти.

Поэтому при вызове ArrayResize(a, 1000) будет выделено памяти под 1000 элементов, а при вызове ArrayResize(a, 1000, 1000) - под 2000 элементов (1000 + 1000). Но при попытках обратиться сразу к элементам с индексами от 1000 до 1999 будет пока что генерироваться ошибка. 

Если вы после этого вызываете ArrayResize(a, 2000), то нового выделения памяти и копирования существующих 1000 элементов в новое место не произойдёт (то есть мы избежали относительно долгой операции), и теперь можно будет обращаться к элементам по индексам от 0 до 1999.

То же самое случится и при вызове  ArrayResize(a, 2000, 1000) вместо ArrayResize(a, 2000), так как если резервное место уже есть и новый запрошенный размер укладывается в резерв, то третий параметр будет игнорироваться.

 
Есть еще вариант документации в виде учебника - может быть там, в разделе про динамические массивы, более понятным покажется "развернутый" пример с ArrayResize.
Учебник по MQL5: Общеупотребительные функции / Работа с массивами / Динамические массивы
Учебник по MQL5: Общеупотребительные функции / Работа с массивами / Динамические массивы
  • www.mql5.com
Общеупотребительные функции - Программирование на MQL5 для трейдеров - Учебник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
Причина обращения: