В теме в общем все сказано. В основном в такой ситуации:
boost::scoped_array<int> p(new int[10]);
Есть ли заметная разница в производительности между исполнением: &p[0] и p.get()?
Я спрашиваю, потому что предпочитаю первый, у него более естественный указатель, например синтаксис. Фактически, это позволяет вам заменить p собственным указателем или массивом и не менять что-либо еще.
Я предполагаю, поскольку get - это однострочный "return ptr;", который компилятор встроит в него, и я надеюсь, что он достаточно умен, чтобы встроить operator[] таким образом, чтобы он не разыменовывался, а затем сразу ссылался.
Кто-нибудь знает?





Единственный способ узнать это - действительно измерить!
Но если у вас есть источник boost: scoped_array, вы можете заблокировать код и посмотреть, что он делает. Я уверен, что это очень похоже.
T * scoped_array::get() const // never throws
{
return ptr;
}
T & scoped_array::operator[](std::ptrdiff_t i) const // never throws
{
BOOST_ASSERT(ptr != 0);
BOOST_ASSERT(i >= 0);
return ptr[i];
}
Напишите две версии кода (одну с помощью get (), другую с помощью оператора []). Скомпилировать в сборку с включенной оптимизацией. Посмотрите, действительно ли вашему компилятору удается оптимизировать ptr + 0.
Вы спрашиваете, достаточно ли умен компилятор, чтобы оптимизировать "ptr + 0". Проверьте вывод вашего компилятора.
хех, можно просто сказать "я не знаю" :-P. Во всяком случае, я знаю, что если бы p был родным указателем, он мог бы. Я полагаю, если параметр operator [] известен во время компиляции, должен сможет все это учесть. Интересно, есть ли это.
Я бы сказал, что невозможно узнать ответ без более точной информации. Поскольку вам легко сделать все самому, возможно, вам стоит попробовать это вручную ;-)
Хорошо, я провел несколько базовых тестов в соответствии с предложениями Мартина Йорка.
Кажется, что g ++ (4.3.2) на самом деле неплохо справляется с этим. На обоих уровнях оптимизации -O2 и -O3 он выводит немного разные, но функционально эквивалентные сборки как для &p[0], так и для p.get().
На -Os, как и ожидалось, он выбрал путь наименьшей сложности и отправляет вызов operator[]. Следует отметить, что версия &p[0] действительно заставляет g ++ генерировать копию тела operator[], но она никогда не используется, поэтому есть небольшое раздувание кода, если вы никогда не используете operator[] в противном случае:
Тестируемый код был следующим (с #if и 0, и 1):
#include <boost/scoped_array.hpp>
#include <cstdio>
int main() {
boost::scoped_array<int> p(new int[10]);
#if 1
printf("%p\n", &p[0]);
#else
printf("%p\n", p.get());
#endif
}
Вы определяли NDEBUG? Я не уверен, как BOOST_ASSERT запускается / деактивируется, но обычные утверждения полностью деактивируются, когда определяется NDEBUG, а затем точно такой же код должен быть испущен при высокой оптимизации по причине, упомянутой Мартином (и предположению, что &*ptr == ptr).
Вау, хороший вызов, asm - это идентичный с -DNDEBUG, если вы предоставите ответ, содержащий это, я его приму.
Это вопрос, который вы задаете просто для академического интереса, или это касается какого-то текущего кода, который вы пишете?
В общем, люди рекомендуют, чтобы ясность кода была важнее скорости, поэтому, если вы не уверены, что это будет иметь значение, вы должны выбрать тот вариант, который более ясен и соответствует вашей базе кода. FWIW, я лично считаю, что get () понятнее.
Сугубо академические причины. Когда я добавил несколько умных указателей в старый код, у меня возникло любопытство. Я понял, что использование & p [0] означает меньше изменений, потому что оно работает и с обычными указателями.
Я посмотрел на источник, operator [] в основном просто выполняет "return ptr [i];" (есть некоторые утверждения, но важен именно код). Мой вопрос: достаточно ли умен компилятор, чтобы знать, что & ptr [0] == ptr в этом случае использования функции operator [].