C++ для использования временной переменной цикла

Считается ли

git add -A && git commit -m "Your Message"

«единой командой»?

Редактировать на основании ответа @ thefinnomenon ниже :

Чтобы получить его как git alias, используйте:

git config --global alias.coa '!git add -A && git commit -m'

и зафиксируйте все файлы, включая новые, с сообщением:

git coa "A bunch of horrible changes"

Объяснение (из git add документации ):

-A, --all, --no-ignore-removal

Обновлять индекс не только там, где В рабочем дереве есть соответствие файла, но также там, где в индексе уже есть запись. Это добавляет, изменяет и удаляет записи индекса, чтобы соответствовать рабочему дереву.

Если не задано при использовании опции -A, обновляются все файлы во всем рабочем дереве (старые версии Git использовались для ограничения обновления текущим каталогом и его подкаталогами).

5
задан Amol Gawai 25 June 2009 в 05:12
поделиться

14 ответов

Пример (b) имеет другое значение, чем пример (a), и компилятор должен интерпретировать его, когда вы его пишете.

Если, (по какой-то надуманной причине, что я могу не думаю), я написал код для этого:

for( int i(0);i < vec.length(); ++i)
{
    if(i%4 == 0)
       vec.push_back(Widget());
}

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

12
ответ дан 12 December 2019 в 11:34
поделиться

Почему это вам суждено? Эти две альтернативы не делают того же самого. Один выполняет фиксированное количество итераций, а другой зависит от тела цикла.

Другой альтернативный вариант:

for (vector<T>::iterator it=vec.begin();it!=vec.end();it++){
 //loop body
}
2
ответ дан 12 December 2019 в 11:34
поделиться

Если вам не нужна переменная цикла вне цикла, второй подход предпочтительнее.

Итераторы фактически дадут вам такую ​​же или лучшую производительность. (Несколько лет назад был большой поток сравнений на comp.lang.c ++., Модерированный.)

Кроме того, я бы использовал

int i = 0;

, а не конструктор, подобный синтаксису, который вы используете. Хотя это действительно так, это не идиоматика.

2
ответ дан 12 December 2019 в 11:34
поделиться

Мне нравится:

for (int i = 0, e = vec.length(); i != e; ++i)

Конечно, это также будет работать для итераторов:

for (vector<int>::const_iterator i = v.begin(), e = v.end(); i != e; ++i)

Мне это нравится, потому что это одновременно эффективно (вызов end () только один раз) , а также относительно лаконично (достаточно ввести vector :: const_iterator один раз).

10
ответ дан 12 December 2019 в 11:34
поделиться

Здесь необходимо обсудить два вопроса:

  1. Область действия переменной
  2. Повторная оценка конечного условия

Область действия переменной

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

Переоценка конечного условия

Эндрю Шеперд красиво сформулировал это: это означает нечто иное, чтобы поместить вызов функции внутри конечного условия:

for( vector<...>::size_type i = 0; i < v.size(); ++i ) { // vector size may grow.
   if( ... ) v.push_back( i ); // contrived, but possible
}

// note: this code may be replaced by a std::for_each construct, the previous can't.
for( vector<...>::size_type i = 0, elements = v.size(); i != elements; ++i ) {
}
3
ответ дан 12 December 2019 в 11:34
поделиться

Скорее не связано:

Предупреждение: сравнение знаковых и беззнаковых целых чисел.

Правильный тип для массивов и векторных индексов - size_t .

Строго говоря, в C ++ это даже std :: vector <> :: size_type .

Удивительно, сколько разработчиков C / C ++ все еще ошибаются.

2
ответ дан 12 December 2019 в 11:34
поделиться

Компилятору очень сложно поднять вызов vec.length () , зная, что он постоянный, если только он не будет встроен (что, надеюсь, часто будет! ). Но по крайней мере i определенно следует объявить во втором стиле «b», даже если вызов length необходимо «вручную» вывести из цикла!

0
ответ дан 12 December 2019 в 11:34
поделиться

Предпочтительнее этот:

typedef vector<int> container; // not really required,
                               // you could just use vector<int> in for loop

for (container::const_iterator i = v.begin(); i != v.end(); ++i)
{
    // do something with (*i)
}
  • Сразу могу сказать, что вектор не обновляется
  • кто угодно может сказать, что происходит здесь
  • Я знаю, сколько циклов
  • v.end () возвращает указатель один за последний элемент, поэтому нет накладных расходов размер проверки
  • легко обновляется для разных контейнеры или типы значений
0
ответ дан 12 December 2019 в 11:34
поделиться

Следует отметить, что примеры итераторов:

for (vector<T>::iterator it=vec.begin();it!=vec.end();it++){
 //loop body
}

могут сделать недействительным итератор цикла «it», если тело цикла вызовет перераспределение вектора. Таким образом, это не эквивалентно

for (int i=0;i<vec.size();++i){
 //loop body
}

, где тело цикла добавляет элементы к vec.

1
ответ дан 12 December 2019 в 11:34
поделиться

Простой вопрос: изменяете ли вы vec в цикле?

ответ на этот вопрос также приведет к вашему ответу.

jrh

0
ответ дан 12 December 2019 в 11:34
поделиться

Я удивлен, что никто не сказал очевидного:

В 99,99% случаев это не имеет значения.

Если только вы не используете какой-то контейнер, в котором вычисляется размер () - дорогостоящая операция, непостижимо, что ваша программа будет работать даже на несколько наносекунд медленнее. Я бы посоветовал придерживаться более удобочитаемого кода, пока вы не профилируете свой код и не обнаружите, что size () является узким местом.

5
ответ дан 12 December 2019 в 11:34
поделиться

Почему бы не обойти эту проблему полностью с помощью BOOST_FOREACH

#include <boost/foreach.hpp>

std::vector<double> vec;

//...

BOOST_FOREACH( double &d, vec)
{
    std::cout << d;
}
0
ответ дан 12 December 2019 в 11:34
поделиться

Посмотрим на сгенерированный код (я использую MSVS 2008 с полной оптимизацией).

a.

int i(0), iMax(vec.size());//vec is a container, say std::vector
for(;i < iMax; ++i)
{
  //loop body
}

Цикл for производит 2 инструкции ассемблера.

b.

for( int i(0);i < vec.size(); ++i)
{
  //loop body
}

Цикл for производит 8 инструкций ассемблера. vec.size () успешно встроен.

c.

for (std::vector<int>::const_iterator i = vec.begin(), e = vec.end(); i != e; ++i)
{
  //loop body
}

Цикл for создает 15 инструкций ассемблера (все встроено, но в коде много переходов)

Итак, если ваше приложение критично по производительности, используйте а). В противном случае b) или c).

1
ответ дан 12 December 2019 в 11:34
поделиться

(b) won't calculate/call the function each time.

-- begin excerpt ----

Loop Invariant Code Motion: GCC включает инвариантное движение кода цикла как часть своего оптимизатора цикла, а также в проход устранения частичной избыточности. Эта оптимизация удаляет инструкции из циклов, которые вычисляют значение, которое не изменяется в течение всего времени существования цикла.

--- конец отрывка -

Дополнительные оптимизации для gcc:

https://www.in .redhat.com / software / gnupro / Technical / gnupro_gcc.php3

0
ответ дан 12 December 2019 в 11:34
поделиться
Другие вопросы по тегам:

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