Должен ли я вывести временные объявления переменных из циклов в C и C ++? - PullRequest
6 голосов
/ 28 июля 2010

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

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
    */
}

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

Спасибо, Бода Цидо.

Ответы [ 6 ]

13 голосов
/ 28 июля 2010

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

2 голосов
/ 28 июля 2010

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

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

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

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

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

1 голос
/ 28 июля 2010

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

0 голосов
/ 28 июля 2010

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

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

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

0 голосов
/ 28 июля 2010

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

0 голосов
/ 28 июля 2010

Вы должны профилировать и убедиться сами. Проверьте этот вопрос (и принятый ответ) моего в качестве ссылки. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;

...