Вектор C++ в / [] скорость оператора

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

curr = myvec.at( i );
doThis( curr );
doThat( curr );
doStuffWith( curr );

Но я должен сделать:

doThis( myvec.at( i ) );
doThat( myvec.at( i ) );
doStuffWith( myvec.at( i ) );

(как ответы моего другого вопроса, на который указывают)

  • Я собираюсь сделать партию ада вызовов к myvec.at() затем. Как быстро это, по сравнению с первым примером с помощью переменной для хранения результата?

  • Существует ли другая опция для меня? Я могу так или иначе использовать указатели?

Когда это станет серьезным будут тысячи вызовов к myvec.at() в секунду. Таким образом, каждая маленькая производительность едок важна.

7
задан sub 5 April 2010 в 13:39
поделиться

9 ответов

Вы можете использовать ссылку:

int &curr = myvec.at(i);
// do stuff with curr

Функция-член at выполняет проверку границ, чтобы убедиться, что аргумент находится в пределах размера вектор . Профилирование - это единственный способ точно узнать, насколько он медленнее по сравнению с оператором [] . Использование ссылки здесь позволяет вам выполнить поиск один раз, а затем использовать результат в других местах. И вы можете сделать его ссылкой на- const , если хотите защитить себя от случайного изменения значения.

18
ответ дан 6 December 2019 в 06:13
поделиться

Параметры, которые я вижу, примерно в обратном порядке предпочтения :

  1. Храните указатели в вашем контейнере вместо фактических объектов. В любом случае это может быть целесообразно, если объекты достаточно сложны, и их копирование проблематично.
  2. Используйте оператор индексации [] вместо в () .
  3. Просто вызовите в () один раз и сохраните его в качестве ссылки (см. Ответ Кристо выше).
  4. Забудьте об этом, пока у вас действительно не возникнет проблема с чрезмерным временем выполнения. Если это произойдет, сначала профилируйте свой код, чтобы убедиться, что здесь узкое место, и только затем беспокойтесь о выполнении одного из вышеперечисленных действий, чтобы ускорить процесс.

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

1
ответ дан 6 December 2019 в 06:13
поделиться

Из моих собственных тестов с аналогичным кодом (скомпилирован под gcc и Linux), оператор [] может быть заметно быстрее, чем на , не из-за проверки границ, а из-за накладных расходов на обработку исключений. Замена на (которая генерирует исключение при выходе за пределы) моей собственной проверкой границ, которая вызывала assert при выходе за пределы, дала ощутимое улучшение.

Использование ссылки, как Кристо сказал , позволяет вам только один раз понести накладные расходы на проверку границ.

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

Однако, как сказал Крис Бек, альтернативы профилированию нет.

4
ответ дан 6 December 2019 в 06:13
поделиться

Векторы наиболее подходят для скорости доступа. Доступ к случайному элементу в векторе имеет сложность O (1) по сравнению с O (n) для общих связанных списков и O (log n) для деревьев ссылок.

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

0
ответ дан 6 December 2019 в 06:13
поделиться

Оператор [] может быть быстрее, чем в , потому что он не требует проверки границ.

Вы можете сделать curr ссылкой, чтобы делать то, что вы хотите.

MyClass & curr = myvec.at(i);

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

2
ответ дан 6 December 2019 в 06:13
поделиться

Причина, по которой первое не работает, заключается в том, что вы не устанавливаете указатель или итератор на адрес i-й переменной. Вместо этого вы устанавливаете curr равным значению i-й переменной, а затем изменяете curr. Я предполагаю, что doThis и doThat являются ссылками.

Сделайте это:

MyObject& curr = myvec.at( i );
2
ответ дан 6 December 2019 в 06:13
поделиться

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

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

пс. Если производительность действительно является проблемой, я получил увеличение скорости в 10 раз из декодера png, удалив векторы и заменив их необработанными массивами. Опять же, это было для Visual Studio 6. Я не утверждаю, что подстановка необработанного массива даст вам улучшение в 10 раз, но это то, что нужно попробовать.

2
ответ дан 6 December 2019 в 06:13
поделиться

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

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

0
ответ дан 6 December 2019 в 06:13
поделиться

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

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

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

0
ответ дан 6 December 2019 в 06:13
поделиться
Другие вопросы по тегам:

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