Объявление переменных за циклом или внутри цикла?

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
pivalexander
299
pivalexander  
   string st = "";
   for (int i = 0; i < 1000; i++)
   {
      st = i;
      ...
   }

или

   for (int i = 0; i < 1000; i++)
   {
      string st = i;
      ...
   }

Есть ли разница? с учетом всех оптимизаций компилятора mql5?

Alexey Navoykov
4571
Alexey Navoykov  
pivalexander:

или

Есть ли разница? с учетом всех оптимизаций компилятора mql5?

Разницы в компиляции нет, так что смело используйте второй вариант.
Georgiy Merts
9181
Georgiy Merts  

Лично я предпочитаю первый.

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

Ну и приравнивание int к string без преобразования - это плохая практика.

Vict
732
Vict  
pivalexander:

Есть ли разница? с учетом всех оптимизаций компилятора mql5?

Не слушайте, что разницы нет. Используйте лишь первый вариант, разница есть. Хотя от мкл дизассм не штудировал.

Alexey Volchanskiy
27265
Alexey Volchanskiy  
Georgiy Merts:

Лично я предпочитаю первый.

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

Ну и приравнивание int к string без преобразования - это плохая практика.

Жорж прав, это не гарантированно.

И получаем варнинг implicit conversion from 'number' to 'string'


И   А вот так точно избавляемся от неопределенности и варнинга

for (int i = 0; i < 1000; i++)
   {
      static string st = IntegerToString(i);
      ...
   }
Alexey Navoykov
4571
Alexey Navoykov  
Georgiy Merts:

Лично я предпочитаю первый.

На всякий случай. Компилятор-то может быть и достаточно умным, чтобы не выделять память каждый раз, но в первом случае я это указываю явно, а вот во втором - это неявный результат работы компилятора

Вы не шутите?  Это настолько тривиальная ситуация для компилятора, что тут даже говорить нечего.  А с такой паранойей можно надо чисто на ассемблере кодировать )  Хотя даже это уже становится бессмысленным по нынешним временам.  Чтобы переплюнуть оптимизации современных компиляторов - это надо очень сильно постараться.

p.s. Возможно я немного погорячился насчёт тривиальности в данном случае, т.к. речь идёт о буфере строки. Но он гарантированно сохраняется в MQL.  Причём не только внутри цикла, но даже между вызовами функции. Тут не раз обсуждалась эта тема
Vict
732
Vict  

Не слушайте, вам тут понараскажут ))

// c++
#include <iostream>
#include <string>
using namespace std;

void* operator new(size_t sz) {
    void *ptr = std::malloc(sz);
    if (ptr)
        return ptr;
    else
        throw std::bad_alloc{};
}


int main() {
        for (uint i = 0;  i < 3;  ++ i) {
                string s;
                char buf[10];
                sprintf(buf, "%u", i);
                s = "sfjhidfsrtea111";
                s += buf;
                cout << s << '\n';
        }
}

Компилирую gcc -O3, запускаю под отладчиком, ставлю точку останова на operator new, получаю три вызова. С clang аналогично.

Зы: если стринг вынести за цикл, то вызов один.

Georgiy Merts
9181
Georgiy Merts  
Alexey Navoykov:

Вы не шутите?  Это настолько тривиальная ситуация для компилятора, что тут даже говорить нечего.  А с такой паранойей можно надо чисто на ассемблере кодировать )  Хотя даже это уже становится бессмысленным по нынешним временам.  Чтобы переплюнуть оптимизации современных компиляторов - это надо очень сильно постараться.

p.s. Возможно я немного погорячился насчёт тривиальности в данном случае, т.к. речь идёт о буфере строки. Но он гарантированно сохраняется в MQL.  Причём не только внутри цикла, но даже между вызовами функции. Тут не раз обсуждалась эта тема

Нет. Не шучу.

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

Просто я считаю, что "на компилятор надейся, а сам не плошай". В стандарте компилятора принято, что локальная переменная создается в момент объявления, и удаляется при выходе из блока, в котором она была объявлена. А значит, на этот принцип и надо ориентироваться в первую очередь, а не ждать, что компилятор за тебя будет улучшать твой код.

Здесь речь, скорее, даже не об эффективности (современные компиляторы, и правда, дают очень качественный код), а об "схеме мышления" самого программиста.  Глядя на исходники из Кодобазы - я нередко поражаюсь, сколько мелких и простых, но потенциально опасных недочетов в них содержится. В данном случае - все еще не сильно критично, максимум, что может случиться - программа будет работать чуть медленнее. Реальные ошибки бывают куда хитрее. 

Alexey Navoykov
4571
Alexey Navoykov  
Vict:

Не слушайте, вам тут понараскажут ))

Компилирую gcc -O3, запускаю под отладчиком, ставлю точку останова на operator new, получаю три вызова. С clang аналогично.

Зы: если стринг вынести за цикл, то вызов один.

А он и не смог делать иначе, т.к. вы сами помешали оптимизации своими брейкпоинтами.  Суть оптимизации в том, что она не должна менять логику алгоритма. Поэтому обнаружить её явным способом невозможно.  Если там стоит брэйкпоинт, то естественно компилятор не имеет права вырезать этот код.  Вы что предполагали, что компилятор может перескочить через точку останова? )

Обнаружить оптимизацию можно только по скомпилированному коду, ну либо замерив производительность.  Так вот это первое, что надо сделать. И успокоиться )

Dmitriy Skub
12023
Dmitriy Skub  
Ждем замеров)
Vict
732
Vict  
Alexey Navoykov:

А он и не смог делать иначе, т.к. вы сами помешали оптимизации своими брейкпоинтами.  Суть оптимизации в том, что она не должна менять логику алгоритма. Поэтому обнаружить её явным способом невозможно.  Если там стоит брэйкпоинт, то естественно компилятор не имеет права вырезать этот код.  Вы что предполагали, что компилятор может перескочить через точку останова? )

Обнаружить оптимизацию можно только по скомпилированному коду, ну либо замерив производительность.  Так вот это первое, что надо сделать. И успокоиться )

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

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

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий