Влияние на производительность & p [0] по сравнению с p.get () в boost :: scoped_array

В теме в общем все сказано. В основном в такой ситуации:

boost::scoped_array<int> p(new int[10]);

Есть ли заметная разница в производительности между исполнением: &p[0] и p.get()?

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

Я предполагаю, поскольку get - это однострочный "return ptr;", который компилятор встроит в него, и я надеюсь, что он достаточно умен, чтобы встроить operator[] таким образом, чтобы он не разыменовывался, а затем сразу ссылался.

Кто-нибудь знает?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
954
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Единственный способ узнать это - действительно измерить!

Но если у вас есть источник 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.

Я посмотрел на источник, operator [] в основном просто выполняет "return ptr [i];" (есть некоторые утверждения, но важен именно код). Мой вопрос: достаточно ли умен компилятор, чтобы знать, что & ptr [0] == ptr в этом случае использования функции operator [].

Evan Teran 08.11.2008 01:50

Вы спрашиваете, достаточно ли умен компилятор, чтобы оптимизировать "ptr + 0". Проверьте вывод вашего компилятора.

Martin York 08.11.2008 01:53

хех, можно просто сказать "я не знаю" :-P. Во всяком случае, я знаю, что если бы p был родным указателем, он мог бы. Я полагаю, если параметр operator [] известен во время компиляции, должен сможет все это учесть. Интересно, есть ли это.

Evan Teran 08.11.2008 01:58

Я бы сказал, что невозможно узнать ответ без более точной информации. Поскольку вам легко сделать все самому, возможно, вам стоит попробовать это вручную ;-)

Martin York 08.11.2008 02:00
Ответ принят как подходящий

Хорошо, я провел несколько базовых тестов в соответствии с предложениями Мартина Йорка.

Кажется, что 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).

Konrad Rudolph 08.11.2008 03:31

Вау, хороший вызов, asm - это идентичный с -DNDEBUG, если вы предоставите ответ, содержащий это, я его приму.

Evan Teran 08.11.2008 05:52

Это вопрос, который вы задаете просто для академического интереса, или это касается какого-то текущего кода, который вы пишете?

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

Сугубо академические причины. Когда я добавил несколько умных указателей в старый код, у меня возникло любопытство. Я понял, что использование & p [0] означает меньше изменений, потому что оно работает и с обычными указателями.

Evan Teran 08.11.2008 05:49

Другие вопросы по теме