Инициализация глобальных переменных программы и другие полезные знания. - страница 3

 
Artyom Trishkin:

Это вы как раз ничего не поняли из того, о чём тут речь. От слова "совсем".

Вот как раз это и был последний Ваш пост, который я прочитал

бай-бай.

 
Renat Akhtyamov:

Давайте разберемся.

Выкопировка принтов с журнала есть?

Замените Comment на Print

В приводимом Артёмом варианте тестового кода вывод итога идёт на каждом тике.

Вы действительно из желания разобраться решили требовать замену там Comment() на Print()? 

Имхо, запись в лог файл торгового терминала через Print() на каждом тике, в данном случае сомнительное удовольствие. Но если вам так удобнее, то просто замените в коде Артёма слово Comment на Print.

Однако сомневаюсь, что другим будет удобнее разбираться в многочисленных записях лога после такой замены (у себя или если вы решите их приложить).

Артём приложил открытый код. При необходимости вы можете его воспроизвести и получить свои независимые результаты. Либо сделать свой вариант.

 
Artyom Trishkin:

Артём, у тебя опечатка в коде (в первой строке вместо testInputInit написан testInputGlobal):

"\n"+"Значение внешней переменной TestInput(",TestInput,"), присвоенное в OnInit(): ",(string)testInputGlobal+
"\n"+"Значение внешней переменной TestInput(",TestInput,"), присвоенное на глобальном уровне: ",(string)testInputGlobal+

Я сейчас чуть попозже приложу ниже другой вариант кода и напишу некоторые уточнения. 

 

А зачем при смене таймфрейма сохранять значения? Надо в ините инициализировать, что бы мусор не оставался.

Кто-то давал гарантию, что после смена таймфрема советник или индикатор загружается по тому же адресу, и что в переменных будут полезные значение, а не мусор?

 
Andrey F. Zelinsky:
Ссылка на раздел документации: https://www.mql5.com/ru/docs/basis/variables/global
"Инициализация глобальных переменных производится однократно после загрузки программы". Кто откуда знает, при смене таймфрейма выгружается программа и загружается снова, или не выгружается? Допустим, когда окно свойств открывается, еще можно быть уверенным, что программа не выгружается. Но когда таймфрейм меняется? - Кто знает, может выгружается и значения сохраняются чисто случайно.
 
Vladimir Karputov:
Вы тему зачем создали? Показать различия поведения переменных. Вот и покажите и осветите всевозможные случаи. Без этого информативность нулевая.

Ты опять по собственному хотению вставляешь свои пункты в правила форума?

Читай пожалуйста https://www.mql5.com/ru/about/rules и не требуй того чего там нет.

 

В общем, поскольку решила сама для себя уточнить некоторые моменты:

 

Приводя инфу о глобальных переменных, Артём сразу сказал, что описываемое им поведение - для экспертов. 

/*в индикаторах поведение отличается*/

Ниже привожу изменённые варианты тестового кода на основе приложенного Артёмом в первом посте. К именам переменных добавила "порядковые" цифровые обозначения.

Подготовила оба ниже прилагаемых тестовых кода в виде:

  • первый вариант:
    • в нём расчётно-итоговая часть в OnInit()): эксперт exTextInitGlobalVariables_0 и индикатор indTextInitGlobalVariables_0;

  • второй вариант:
    •  там расчётно-итоговая часть - в OnTick()/OnCalculate() , где попутно добавлена ограничивающая расчёт переменная static int i: эксперт exTextInitGlobalVariables_1 и индикатор indTextInitGlobalVariables_1. 

Проводимая мной последовательность экспериментов:

  1. Запустить на график первый вариант тестового кода в виде эксперта, 
  2. Затем несколько раз сменить период графика.
  3. Удалить этот тестовый эксперт с графика.
  4. Заново его запустить /* чтобы видеть при запуске, не сохранились ли значения от предыдущего запуска*/
  5. Затем несколько раз сменить период графика. 
  6. Удалить эксперт с графика/не удалять эксперт с графика. 
  7. Запустить на график прилагаемый ниже первый тестовый код в виде индикатора.
  8. Затем сменить период графика.
  9. Удалить тестовый индикатор с графика.
Эта же последовательность для второго прилагаемого варианта тестового кода. 

Т.е., без вариантов экспериментов: при закрытии терминала, удаления/восстановления графика, шаблон. <= Без них - по банальной причине. Я опубликую результаты экспериментов, перечисленных в пронумерованном списке выше, но потом мне надо будет уйти по своим делам. Т.е., сама для себя посмотрю позже.  

Первый тестовый код:

//--- input parameters
input int   TestInput=0;          // Внешняя переменная
//---
int testInputGlobal_0=TestInput;  // Значение внешней переменной, присвоенное на глобальном уровне
int testInputInit_1;              // Значение внешней переменной, присвоенное в OnInit()
//--- global variables
int TestValueGlobalNoInitNo_2;    // Не инициализирована значением нигде
int TestValueGlobalYesInitNo_3=0; // Инициализирована значением 0 при объявлении, не инициализирована в OnInit()
//---
int TestValueGlobalNoInitYes_4;    // Не инициализирована значением при объявлении, инициализирована в OnInit() нулём
int TestValueGlobalYesInitYes_5=0; // Инициализирована нулём и при объявлении, и в OnInit()
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   testInputInit_1=TestInput;
   TestValueGlobalNoInitYes_4=0;
   TestValueGlobalYesInitYes_5=0;
   //---
   testInputGlobal_0++;             //# 0 Значение внешней переменной TestInput(",TestInput,"), присвоенное на глобальном уровне,(string)testInputGlobal_0
   testInputInit_1++;               //# 1 Значение внешней переменной TestInput(",TestInput,"), присвоенное в OnInit(): ",(string)testInputInit_1
   TestValueGlobalNoInitNo_2++;     //# 2 Не инициализирована значением нигде (неявная инициализация нулём): ",(string)TestValueGlobalNoInitNo_2
   TestValueGlobalYesInitNo_3++;    //# 3 Инициализирована значением 0 при объявлении, не инициализирована в OnInit(): "+(string)TestValueGlobalYesInitNo_3
   TestValueGlobalNoInitYes_4++;    //# 4 Не инициализирована значением при объявлении, инициализирована в OnInit() нулём: "+(string)TestValueGlobalNoInitYes_4
   TestValueGlobalYesInitYes_5++;   //# 5 Инициализирована нулём и при объявлении, и в OnInit(): "+(string)TestValueGlobalYesInitYes_5
   //---
   Print
   (
    "\n"+"============================================="+
    "\n"+"# 0 Значение внешней переменной TestInput(",TestInput,"), присвоенное на глобальном уровне (testInputGlobal_0): ",(string)testInputGlobal_0+
    "\n"+"# 1 Значение внешней переменной TestInput(",TestInput,"), присвоенное в OnInit() (testInputInit_1): ",(string)testInputInit_1+
    //---
    "\n"+"============================================="+
    "\n"+"# 2 Не инициализирована значением нигде (неявная инициализация нулём) (TestValueGlobalNoInitNo_2): ",(string)TestValueGlobalNoInitNo_2+
    "\n"+"# 3 Инициализирована значением 0 при объявлении, не инициализирована в OnInit() (TestValueGlobalYesInitNo_3): "+(string)TestValueGlobalYesInitNo_3+
    //---
    "\n"+"============================================="+
    "\n"+"# 4 Не инициализирована значением при объявлении, инициализирована в OnInit() нулём (TestValueGlobalNoInitYes_4): "+(string)TestValueGlobalNoInitYes_4+
    "\n"+"# 5 Инициализирована нулём и при объявлении, и в OnInit() (TestValueGlobalYesInitYes_5): "+(string)TestValueGlobalYesInitYes_5
    );
//---
   return(INIT_SUCCEEDED);
  }
 

Второй тестовый код (вариант для советника, для индикатора же прилагаю файлом, не приводя):

Изменённый позднее вариант (дополнила выводом на печать в OnInit()): 

//--- input parameters
input int   TestInput=0;          // Внешняя переменная
//---
int testInputGlobal_0=TestInput;  // Значение внешней переменной, присвоенное на глобальном уровне
int testInputInit_1;              // Значение внешней переменной, присвоенное в OnInit()
//--- global variables
int TestValueGlobalNoInitNo_2;    // Не инициализирована значением нигде
int TestValueGlobalYesInitNo_3=0; // Инициализирована значением 0 при объявлении, не инициализирована в OnInit()
//---
int TestValueGlobalNoInitYes_4;    // Не инициализирована значением при объявлении, инициализирована в OnInit() нулём
int TestValueGlobalYesInitYes_5=0; // Инициализирована нулём и при объявлении, и в OnInit()
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   testInputInit_1=TestInput;
   TestValueGlobalNoInitYes_4=0;
   TestValueGlobalYesInitYes_5=0;
//---
     Print
      (
       "\n"+"============================================="+
       "\n"+"# 0 OnIn Значение внешней переменной TestInput(",TestInput,"), присвоенное на глобальном уровне (testInputGlobal_0): ",(string)testInputGlobal_0+
       "\n"+"# 1 OnIn Значение внешней переменной TestInput(",TestInput,"), присвоенное в OnInit() (testInputInit_1): ",(string)testInputInit_1+
       //---
       "\n"+"============================================="+
       "\n"+"# 2 OnIn Не инициализирована значением нигде (неявная инициализация нулём) (TestValueGlobalNoInitNo_2): ",(string)TestValueGlobalNoInitNo_2+
       "\n"+"# 3 OnIn Инициализирована значением 0 при объявлении, не инициализирована в OnInit() (TestValueGlobalYesInitNo_3): "+(string)TestValueGlobalYesInitNo_3+
       //---
       "\n"+"============================================="+
       "\n"+"# 4 OnIn Не инициализирована значением при объявлении, инициализирована в OnInit() нулём (TestValueGlobalNoInitYes_4): "+(string)TestValueGlobalNoInitYes_4+
       "\n"+"# 5 OnIn Инициализирована нулём и при объявлении, и в OnInit() (TestValueGlobalYesInitYes_5): "+(string)TestValueGlobalYesInitYes_5);
  //---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   static int i=0;
//---
   if(i<2)
     {
      //---
      testInputGlobal_0++;             //# 0 Значение внешней переменной TestInput(",TestInput,"), присвоенное на глобальном уровне,(string)testInputGlobal_0
      testInputInit_1++;               //# 1 Значение внешней переменной TestInput(",TestInput,"), присвоенное в OnInit(): ",(string)testInputInit_1
      TestValueGlobalNoInitNo_2++;     //# 2 Не инициализирована значением нигде (неявная инициализация нулём): ",(string)TestValueGlobalNoInitNo_2
      TestValueGlobalYesInitNo_3++;    //# 3 Инициализирована значением 0 при объявлении, не инициализирована в OnInit(): "+(string)TestValueGlobalYesInitNo_3
      TestValueGlobalNoInitYes_4++;    //# 4 Не инициализирована значением при объявлении, инициализирована в OnInit() нулём: "+(string)TestValueGlobalNoInitYes_4
      TestValueGlobalYesInitYes_5++;   //# 5 Инициализирована нулём и при объявлении, и в OnInit(): "+(string)TestValueGlobalYesInitYes_5
      //---
      Print
      (
       "\n"+"============================================="+
       "\n"+"# 0 Значение внешней переменной TestInput(",TestInput,"), присвоенное на глобальном уровне (testInputGlobal_0): ",(string)testInputGlobal_0+
       "\n"+"# 1 Значение внешней переменной TestInput(",TestInput,"), присвоенное в OnInit() (testInputInit_1): ",(string)testInputInit_1+
       //---
       "\n"+"============================================="+
       "\n"+"# 2 Не инициализирована значением нигде (неявная инициализация нулём) (TestValueGlobalNoInitNo_2): ",(string)TestValueGlobalNoInitNo_2+
       "\n"+"# 3 Инициализирована значением 0 при объявлении, не инициализирована в OnInit() (TestValueGlobalYesInitNo_3): "+(string)TestValueGlobalYesInitNo_3+
       //---
       "\n"+"============================================="+
       "\n"+"# 4 Не инициализирована значением при объявлении, инициализирована в OnInit() нулём (TestValueGlobalNoInitYes_4): "+(string)TestValueGlobalNoInitYes_4+
       "\n"+"# 5 Инициализирована нулём и при объявлении, и в OnInit() (TestValueGlobalYesInitYes_5): "+(string)TestValueGlobalYesInitYes_5+
       "\n"+"static int i = ",i
       );
      //---
      i++;
     }
//---
  }
 
Dmitry Fedoseev:

А зачем при смене таймфрейма сохранять значения? Надо в ините инициализировать, что бы мусор не оставался.

Кто-то давал гарантию, что после смена таймфрема советник или индикатор загружается по тому же адресу, и что в переменных будут полезные значение, а не мусор?

Скорее соглашусь с Дмитрием.

И кроме того. Вот Артём пишет в самом начале:

...я решил показать на примере маленького тестового советника как лучше инициализировать глобальные переменные ваших программ так, чтобы при смене таймфрейма не терялись значения глобальных переменных, и можно было спокойно переключать таймфрейм графика, на котором установлен советник...

Лучше для кого/чего? Имхо, спорный момент. Скорее всего зависит от целей управления экспертом со стороны его владельца...

 
Dennis Kirichenko:

Скорее соглашусь с Дмитрием.

И кроме того. Вот Артём пишет в самом начале:

Лучше для кого/чего? Имхо, спорный момент. Скорее всего зависит от целей управления экспертом со стороны его владельца...

Для чего.

Для того, чтобы значения не терялись при смене таймфрейма.

Я нигде не говорил, и не утверждал, что всегда нужно делать так.

Я сказал, что при инициализации глобальной переменной советника не в глобальном пространстве, в котором она и находится, а в пространстве OnInit(), она потеряет своё значение при смене таймфрейма. Что не очень верно для некоторых ситуаций, в которых человеку необходимо переключить таймфрейм графика, на котором работает советник, и в тех ситуациях, когда советник использует некие глобальные переменные в своих расчётах.

Привёл код, подтверждающий мой посыл. Хотите - делайте иначе, хотите - учитывайте эту особенность, хотите - не учитывайте. Моя цель была показать различие в методах инициализации глобальной переменной, и результатов каждого метода инициализации при смене таймфрейма. Всё. Больше никаких целей не преследовалось.