Использует размер () для 2-го выражения в для конструкции всегда плохо?

Это может звучать странно, но единственное правильное решение для этого случая - поместить эти настройки в ресурсы. ОС Android собирает ресурсы на основе множества свойств, и одно из них имеет наименьшую ширину. Чтобы отделить список от сетки: values ​​/ bools.xml :

<resources>
    <bool name="is_grid">false</bool>
</resources>

другой будет values-sw520dp / bools.xml :

[ 111]

Для числа столбцов одинаковая логика values-sw520dp / inteers.xml :

<resources>
    <integer name="grid_column_count">2</integer>
</resources>

И values-sw720dp / inteers.xml : 118]

<resources>
    <integer name="grid_column_count">3</integer>
</resources>

Так что в коде это будет что-то вроде:

if (getResources().getBoolean(R.bool.is_grid)) {
    instagram_feeds.setLayoutManager(new GridLayoutManager(getActivity(), getResources().getInteger(R.integer.grid_column_count));
} else {
    instagram_feeds.setLayoutManager(new LinearLayoutManager(getActivity());
}

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

8
задан Tom Williams 3 October 2008 в 13:35
поделиться

16 ответов

Вот один способ сделать это, который делает это явным - размер () называют только однажды.

for (size_t ii = 0, count = values.size();  ii < count;  ++ii)

Править: Меня попросили на самом деле ответить на вопрос, таким образом, вот мой лучший выстрел.

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

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

P.S. Я записал это, прежде чем я прочитал ответ Benoit тщательно, я полагаю, что мы находимся в полном согласии.

14
ответ дан 5 December 2019 в 04:32
поделиться
  • При изменении вектора (добавляющие или удаляющие элементы) в для цикла затем, Вы не должны использовать временную переменную, так как это могло привести к ошибкам.
  • Если бы Вы не изменяете векторный размер в для цикла затем, я все время использовал бы временную переменную для хранения размера (это сделает код независимым в деталях реализации вектора:: размер.
1
ответ дан 5 December 2019 в 04:32
поделиться

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

Затем, конечно, for может стать a while и нет никаких необходимых временных переменных вообще - можно даже передать итератор функции sumVector вместо ссылки/значения константы.

1
ответ дан 5 December 2019 в 04:32
поделиться

Если Вы использовали контейнер где size() был O (n) (как std::list) и не O (1) (как std::vector), Вы не выполнили бы итерации через тот контейнер с помощью индексов. Вы использовали бы итераторы вместо этого.

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

1
ответ дан 5 December 2019 в 04:32
поделиться

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

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

1
ответ дан 5 December 2019 в 04:32
поделиться

Компилятор не будет знать, изменяется ли значение .size () между вызовами, таким образом, это не сделает никакой оптимизации. Я знаю, что Вы просто спросили об использовании .size (), но необходимо использовать итераторы так или иначе.

std::vector<double>::const_iterator iter = values.begin();
for(; iter != values.end(); ++iter)
{
    // use the iterator here to access the value.
}

В этом случае вызов к .end () подобен проблеме, которую Вы выставляете с .size (). Если Вы знаете, что цикл не выполняет операции в векторе, который делает недействительным итераторы, можно инициализировать итератор к .end (), положение до вводит цикл и использование что как граница.

1
ответ дан 5 December 2019 в 04:32
поделиться

Метод размера от станд.:: вектор должен быть встроен компилятором, означая, что каждый вызов к размеру () заменяется его фактическим телом (см. вопрос, Почему я должен когда-либо использовать встроенный код для получения дополнительной информации о встраивании). С тех пор в большей части размера реализаций () в основном вычисляет различие между концом (), и начните () (который должен быть встроен также), Вы не должны волноваться слишком много о потере производительности.

Кроме того, если я помню правильно, некоторые компиляторы достаточно "умны", чтобы обнаружить constness выражения во второй части для конструкции и сгенерировать код, который оценивает выражение только однажды.

1
ответ дан 5 December 2019 в 04:32
поделиться

При содержании размера вектора во временной переменной Вы будете независимы от компилятора.

Мое предположение, что большинство компиляторов оптимизирует код в некотором смысле, тот размер () назовут только однажды. Но использование временной переменной даст Вам гарантию, размер () только назовут однажды!

1
ответ дан 5 December 2019 в 04:32
поделиться

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

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

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

Как небольшое в стороне, никакой компилятор не оптимизировал бы размер () к одному из присвоения вызова временному файлу. Нет почти никакой гарантии константы в C++. Компилятор не может рискнуть предполагать, что размер () возвратит то же значение для целого цикла. Например. Другой поток мог изменить вектор промежуточные повторения цикла.

0
ответ дан 5 December 2019 в 04:32
поделиться

Это не имеет значения вообще. Производительность наверху .at () является столь большой (это содержит условный оператор броска), что неоптимизированная версия проведет большую часть своего времени там. Оптимизирующий компилятор, достаточно умный к eliminiate, условный бросок обязательно определит тот размер (), не изменяется.

2
ответ дан 5 December 2019 в 04:32
поделиться

Это не часть вопроса, но почему Вы используете at в Вашем коде вместо нижнего оператора []?

Смысл в at должен гарантировать, что никакая операция на недопустимом индексе не происходит. Однако это никогда не будет иметь место в Вашем цикле, так как Вы знаете из своего кода, чем индексы будут (всегда принятие однопоточности).

Даже если Ваш код содержал логическую ошибку, заставляя Вас получить доступ к недопустимому элементу, at в этом месте было бы бесполезно, потому что Вы не ожидаете получающееся исключение, и следовательно Вы не рассматриваете его (или делаете Вы включаете все свои циклы try блоки?).

Использование at здесь вводит в заблуждение, потому что это говорит читателю, что Вы (как программист) не знаете то, что оценивает индекс, будет иметь – который является, очевидно, неправильным.

Я соглашаюсь с Curro, это - типичный случай для использования итераторов. Хотя это является более подробным (по крайней мере, если Вы не используете конструкции как Повышение. Foreach), это также намного более выразительно и более безопасно.

Повышение. Foreach позволил бы Вам писать код следующим образом:

double sum = 0.0;
foreach (double d, values)
    sum += d;

Эта работа безопасна, эффективна, коротка и читаема.

2
ответ дан 5 December 2019 в 04:32
поделиться

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

В любом случае это должно действительно быть записано с помощью итератора - поскольку там может больше наверху получать доступ к определенному примеру.

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

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

for (int i=v.size()-1; i>=0 ;i--)
{
   ...
}
2
ответ дан 5 December 2019 в 04:32
поделиться

Неважно, настройки оптимизации, помещая .size () вызов во втором выражении будут самое большее так же производительны как выделение .size () вызов перед для цикла. Это:

size_t size = values.size();
for (size_t ii = 0; ii < size; ++ii) {
    sum += values.at(ii)
}

будет всегда работать, по крайней мере, а также, если не лучше, чем:

for (size_t ii = 0; ii < values.size(); ++ii) {
    sum += values.at(ii);
}

На практике, это, вероятно, вопрос привычки, начиная с выделения .size () вызов является общей оптимизацией компилятора. Однако я действительно нахожу вторую версию легче читать.

Я нахожу это еще легче, хотя:

double sum = std::accumulate(values.begin(), values.end(), 0);
5
ответ дан 5 December 2019 в 04:32
поделиться

Запустите с размера () в 'для' конструкции, пока Вы не должны будете оптимизировать для скорости.

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

9
ответ дан 5 December 2019 в 04:32
поделиться

Я соглашаюсь с Benoit. Введение новой переменной, особенно интервал или даже короткое будет обладать большим преимуществом что, называя это каждым разом.

Это - то меньше вещи волноваться о том, если цикл когда-нибудь становится достаточно большим, что это может повлиять на производительность.

1
ответ дан 5 December 2019 в 04:32
поделиться

Все это зависит от того, какова реализация размера вектора, насколько агрессивный компилятор и если это слушает/использует встроенные директивы.

Я был бы большей обороной и представил бы временный файл, поскольку у Вас нет гарантий о том, насколько эффективный Ваш компилятор будет.

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

Если бы это назовут тысячами времен, то я использовал бы временный файл.

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

Мне нелегко рассматривать то, что является рефакторингом, чтобы быть оптимизацией. Но в конце, это вроде "Вас, говорят, что помидор, я говорю помидор"...

12
ответ дан 5 December 2019 в 04:32
поделиться
Другие вопросы по тегам:

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