Есть ли совпадения для разыменования std:: tr1: shared_ptr по сравнению с разыменованием открытого указателя?

#c #pointers #boost #smart-pointers #tr1

#c #указатели #повышение #интеллектуальные указатели #tr1

Вопрос:

Я понимаю, что существует (иногда значительное) снижение производительности при создании, назначении, копировании и уничтожении std:: tr1::shared_ptr или boost::shared_ptr (из-за механизмов подсчета ссылок). Правильно ли, что после создания доступ к указателю, обернутому shared_ptr, не приводит к снижению производительности?

другими словами: учитывая

 std::tr1::shared_ptr<myClass> SharedA(new myClass);
myClass *NakedA = new myClass;
  

делает

 SharedA->someClassMember
  

имеют те же накладные расходы, что и

 NakedA->someClassMember
  

?

Комментарии:

1. я не знаю, что происходит, когда вы его измеряете?

2. Каков выбор? Не использовать shared_ptr, хотя это необходимо?

3. @Doug T.- В простых тестовых примерах это, похоже, не имеет значения, однако в большом коде, над которым я работаю, мой профилировщик показывает некоторые накладные расходы при доступе к указателю (хотя кажется, что он должен быть встроенным и, следовательно, не имеет значения)

4. @Bo- технически управляемый указатель «не нужен». Это, как правило, хороший выбор дизайна, и в большинстве случаев его следует использовать. В моем случае (код научно-исследовательской группы) Я могу позволить себе накладные расходы на построение / назначение / etc, Но доступ к shared_ptr слишком сильно замедляет работу, и, насколько я понимаю, этого не должно быть.

5. Какой профилировщик вы используете? Профилировщик выборки не должен быть в состоянии определить разницу, если operator-> метод был встроен. Инструментальный профилировщик будет регистрировать вызов метода, несмотря ни на что, и измерение будет искажено, потому что он не будет измерять использование простого старого -> оператора для простых старых указателей, потому что он вообще не будет использовать эти инструкции.

Ответ №1:

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

(Это то, что делает std::shared_ptr реализация Visual C 2010: каждый из этих перегруженных операторов просто вызывает функцию «get», которая просто возвращает указатель; нет блокировки или других накладных расходов любого рода. Другие реализации могут отличаться.)

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

Комментарии:

1. Спасибо, Джеймс — это то, что я подозревал, но не хотел продолжать преследовать свой хвост, если я не видел ясно.

Ответ №2:

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