Ошибки, баги, вопросы - страница 2045

 

И вот ещё по теме инициализации переменных.  Если следовать тому, что было указано в документации, тогда и ссылаться на другие глобальные/статические переменные тоже нельзя.  Т.к. это не является константным выражением:

int a= 1;
int b= a+1;  // Согласно документации, такая инициализация не возможна

void OnStart()
{
  Print(b);
}

Однако пока это работает.  И я полагаю, многие всегда пользовались такими конструкциями, ничего не подозревая.  Но выходит что в любой момент разработчики могут отрубить это.  И как и в случае с инициализацией функциями, эти коды будут продолжать успешно компилироваться, но станут работать неправильно.  В общем, весь MQL - это мина замедленного действия.

 
Alexey Navoykov:

И вот ещё по теме инициализации переменных.  Если следовать тому, что было указано в документации, тогда и ссылаться на другие глобальные/статические переменные тоже нельзя.  Т.к. это не является константным выражением:

//+------------------------------------------------------------------+
//|                                                   ExpertMACD.mq5 |
//|                   Copyright 2009-2017, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
CExpert ExtExpert;

инициализируется функцией-конструктором - запретить!

Это если логически обобщить последние сообщения

Alexey Navoykov:

Обнаружил причину несоответствия.  В режиме OPTIMIZE=0 ошибка есть, а с OPTIMIZE=1 нет.   Я обычно всегда только OPTIMIZE=0 пользуюсь

В 32-разрядном терминале ошибка при любом OPTIMIZE

int g1( int& t[] ) { return ArraySize( t ); }
int g2( int& t[] ) { return g1( t ); }
void OnStart()
{
        int t[] = { 1, 2, 3, 4, 5 }; //всего 5
        Print( g2(t)); //Результат:          3
}
 
A100:

инициализируется функцией-конструктором - запретить!

Это если логически обобщить последние сообщения

Ну там просто человек некорректно выразился.  Конечно речь идёт об инициализирующем значении, а не о об инициализирующей функции.


Да и бог с ними с запретами. Они сами по себе не несут проблем. Но вот когда этот запрет никак не контролируется компилятором, а вместо этого порождая алгоритм, работающий в обход правил языка, то это вообще ни в какие рамки не лезет.   Теперь придётся перелопачивать все коды, выискивая такие моменты, да и вообще постоянно быть настороже.  Ну его нафиг такое программирование, лучше останусь на старом билде.

 
Alexey Navoykov:
Ясно, тогда прошу прощения, не заметил сразу.  Удивительно конечно, как они успели втихаря это поменять, и ничего никому не сказали.  Тогда не понятно, почему компилятор никак не реагирует на то, что выполняется недопустимая операция.   Т.е. баг в любом случае имеет место
Почему вы думаете что поменяли, почему она недопустимая? Пожалуйста пользуйтесь на своё усмотрение. Вся проблема в том, что при инициализации статической переменной функцией, "приостанавливается" инициализация и выполняется эта функция. А в приведённом примере, в той функции ещё есть статическая переменная которая пока ещё не инициализирована. Отсюда и переменная инициализированная функцией принимает не соответствующее значение.
 
Alexey Navoykov:

И вот ещё по теме инициализации переменных.  Если следовать тому, что было указано в документации, тогда и ссылаться на другие глобальные/статические переменные тоже нельзя.  Т.к. это не является константным выражением:

Однако пока это работает.  И я полагаю, многие всегда пользовались такими конструкциями, ничего не подозревая.  Но выходит что в любой момент разработчики могут отрубить это.  И как и в случае с инициализацией функциями, эти коды будут продолжать успешно компилироваться, но станут работать неправильно.  В общем, весь MQL - это мина замедленного действия.

Ну... никакого расхождения с описанием в документации в этом примере НЕТ... Внимательно изучите цитату из документации

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


или константным выражением

int a= 1;
int b= a+1;

Такая инициализация возможна. Потому, что переменная 'а' инициализируется константой, а переменная 'b' инициализируется константным выражением.

 
A100:

Тогда нужно запретить статические экземпляры классов - потому что они инициализируются функцией-конструктором

Обратите внимание на

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Ошибки, баги, вопросы

Alexey Viktorov, 2017.10.18 09:19

Почему вы думаете что поменяли, почему она недопустимая? Пожалуйста пользуйтесь на своё усмотрение. Вся проблема в том, что при инициализации статической переменной функцией, "приостанавливается" инициализация и выполняется эта функция. А в приведённом примере, в той функции ещё есть статическая переменная которая пока ещё не инициализирована. Отсюда и переменная инициализированная функцией принимает не соответствующее значение.
Допустимо-ли в конструкторе объявлять и инициализировать статические переменные, увы, я не знаю, но надеюсь вы скажете об этом. И, как я понял, очень важна последовательность инициализации.
 
Alexey Viktorov:

Такая инициализация возможна. Потому, что переменная 'а' инициализируется константой, а переменная 'b' инициализируется константным выражением.

'b' здесь инициализируется НЕ константным выражением.  Поэтому это противоречит правилам, описанным в документации.

Вся проблема в том, что при инициализации статической переменной функцией, "приостанавливается" инициализация и выполняется эта функция. А в приведённом примере, в той функции ещё есть статическая переменная которая пока ещё не инициализирована. Отсюда и переменная инициализированная функцией принимает не соответствующее значение.

Да как инициализация может приостанавливаться то.  Все операции выполняются в строгом порядке, определённом синтаксисом языка.  Сначала выполняется функция, затем возвращаемое значение этой функции передаётся в конструктор нашей переменной - это называется инициализацией.  А в данном случае операция инициализации нагло игнорируется компилятором, и код компилируется дальше, как ни в чём не бывало. Это недопустимо.    Это то же самое, как если бы ты например объявил такой массив:  int a[]= { f(), g(), h() };  и оно бы компилировалось, но естественно ничего при этом не инициализируя.  

 
A100:

В 32-разрядном терминале ошибка при любом OPTIMIZE

Реально.  Проверил в МТ4, действительно ошибки при любом раскладе.  И как народ там что-то кодит на новых билдах
 
Alexey Navoykov:

'b' здесь инициализируется НЕ константным выражением.  Поэтому это противоречит правилам, описанным в документации.

Да как инициализация может приостанавливаться то.  Все операции выполняются в строгом порядке, определённом синтаксисом языка.  Сначала выполняется функция, затем возвращаемое значение этой функции передаётся в конструктор нашей переменной - это называется инициализацией.  А в данном случае операция инициализации нагло игнорируется компилятором, и код компилируется дальше, как ни в чём не бывало. Это недопустимо.    Это то же самое, как если бы ты например объявил такой массив:  int a[]= { f(), g(), h() };  и оно бы компилировалось, но естественно ничего при этом не инициализируя.  

Если не константным выражением, то ЧЕМ???

Алексей, проще будет если сам возьмёшь тот код и посмотришь в дебагере последовательность инициализации. И ещё, я не сразу заметил, что в этом примере

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Ошибки, баги, вопросы

Alexey Navoykov, 2017.10.17 20:31

И вот ещё по теме инициализации переменных.  Если следовать тому, что было указано в документации, тогда и ссылаться на другие глобальные/статические переменные тоже нельзя.  Т.к. это не является константным выражением:

int a= 1;
int b= a+1;  // Согласно документации, такая инициализация не возможна

void OnStart()
{
  Print(b);
}

Однако пока это работает.  И я полагаю, многие всегда пользовались такими конструкциями, ничего не подозревая.  Но выходит что в любой момент разработчики могут отрубить это.  И как и в случае с инициализацией функциями, эти коды будут продолжать успешно компилироваться, но станут работать неправильно.  В общем, весь MQL - это мина замедленного действия.


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

У меня не хватает знаний чтобы доступно объяснить, а у вас не хватает внимательности. "приостанавливается" в кавычках!!!

Не надо сваливать в одну кучу инициализацию статических и обычных переменных, тем-более локальных.

 
Alexey Viktorov:

Если не константным выражением, то ЧЕМ???

Неконстантным выражением.

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

У меня не хватает знаний чтобы доступно объяснить, а у вас не хватает внимательности...

Вы ничего не путаете?

Более того, глобальные и статические переменные ведут себя абсолютно идентично.  Вот из документации:

Глобальная переменная может быть проинициализирована только соответствующей ее типу константой либо константным выражением.

Признаюсь, для меня это было таким же открытием, как и со статическими переменными.  Уж не знаю, когда это всё появилось в документации, а может и было раньше, просто никто не обращал внимания, т.к. по факту всё работало как в C++, потому вопросов не возникало.