Я должен вывести объявления временной переменной из циклов в C и C++?

Вот то, что я имею в виду, предполагаю, что у меня есть код как:

for (int i = 0; i < 1000; i++) {
    char* ptr = something;
    /*
    ... use ptr here
    */
}

Это кажется этим char* ptr выделяется каждый раз в цикле, делая это неэффективным?

Действительно ли более эффективно записать это?

char* ptr = something;
for (int i = 0; i < 1000; i++) {
    /*
    ... use ptr here
    */
}

Прокомментируйте эту интересную проблему.Спасибо!

Спасибо, Boda Cydo.

6
задан bodacydo 28 July 2010 в 13:27
поделиться

6 ответов

Это может повлиять на производительность, но многие оптимизирующие компиляторы при необходимости проводят эту оптимизацию за вас. Это называется « движение кода с инвариантным циклом ».

13
ответ дан 8 December 2019 в 14:39
поделиться

Вы должны зарегистрироваться и убедиться в этом сами. Просмотрите этот (и принятый ответ) мой в качестве справки. Как говорит jalf , это просто практическое правило - ожидать, что он будет оптимизирован (и, вероятно, это правильно для типов POD) , но вам нужно будет сделать резервную копию с профилированием.

0
ответ дан 8 December 2019 в 14:39
поделиться

По личному соглашению в программах на 'C' мне нравится помещать объявления переменных вверху функции, вверху файла или в общем файле .h. Если я начну прятать объявления в коде, это может сбить с толку и легко потерять отслеживание области видимости переменной, что приведет к нежелательным последствиям.

0
ответ дан 8 December 2019 в 14:39
поделиться

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

Существует очевидная разница, если ptr переназначается внутри цикла (и если вы не переназначаете его, вы должны сделать его char * const ptr ), в том смысле, что значение будет сохранено с предыдущей итерации вместо сброса.

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

0
ответ дан 8 December 2019 в 14:39
поделиться

Способ транслирования кода в действительности зависит от вашего компилятора и выполняемых им оптимизаций. Компилятор может выполнить «тупой» перевод и выделить каждый цикл, или он может разместить выделение вне цикла для вас на этапе оптимизации. На всякий случай я бы поместил объявление вне цикла. Как и все, вы можете протестировать оба и посмотреть, сколько времени занимает каждый цикл, чтобы увидеть, есть ли разница.

1
ответ дан 8 December 2019 в 14:39
поделиться

Я отношусь к той школе, которая считает, что лучше максимально ограничить область применения имен переменных; если ptr не предназначен для ссылок вне цикла, то его не следует объявлять вне цикла.

Однако если something оказывается дорогой операцией И она инвариантна (т.е. не зависит от i) И она мешает вашему коду выполнить жесткое требование производительности, то да, вам следует вынести объявление за пределы цикла.

Это невыразимо уродливо, но вы можете сделать что-то вроде этого:

do
{
  char *ptr = something;
  for (int i = 0; i < 1000; i++)
  {
    /* use ptr here */
  }
} while (0);

Вы по-прежнему ограничиваете область видимости ptr, но больше не присваиваете его на каждой итерации цикла.

2
ответ дан 8 December 2019 в 14:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: