Производительность C++ Smart Pointer

Насколько использование интеллектуальных указателей, особенно boost :: shared_ptr, стоит дороже по сравнению с голыми указателями с точки зрения времени и памяти? Лучше ли использовать голые указатели для требовательных к производительности частей игровых / встроенных систем? Вы бы порекомендовали использовать голые указатели или интеллектуальные указатели для компонентов, требующих высокой производительности?

Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
18
0
7 786
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Boost предоставляет различные интеллектуальные указатели. Как правило, как занятость памяти, которая зависит от типа интеллектуального указателя, так и производительность не должны быть проблемой. Для сравнения производительности вы можете проверить это http://www.boost.org/doc/libs/1_37_0/libs/smart_ptr/smarttests.htm.

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

Следующий фрагмент демонстрирует отсутствие потери производительности при использовании shared_ptr<> вместо необработанного указателя:

#include <iostream>
#include <tr1/memory>

int main()
{
#ifdef USE_SHARED_PTR
    std::tr1::shared_ptr<volatile int> i(new int(1));
#else
    volatile int * i = new int(1);
#endif

    long long int h = 0;

    for(long long int j=0;j < 10000000000LL; j++)
    {
        h += *i;
    }

    std::cout << h << std::endl;
    return 0;
}
Ответ принят как подходящий

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

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

Фактически, с приближением TR1 вполне вероятно, что компиляторы лучше справятся с интеллектуальными указателями, чем с необработанными указателями. Например. возможно, что компилятор может доказать, что интеллектуальный некопируемый указатель не имеет псевдонима в некоторых ситуациях просто потому, что он не копируемый. Подумайте об этом: псевдонимы возникают, когда создаются два указателя, указывающие на один и тот же объект. Если первый указатель не может быть скопирован, как второй указатель будет указывать на тот же объект? (Есть способы обойти это тоже - оператор * должен возвращать lvalue)

К сожалению, ваша идея оптимизированных интеллектуальных указателей не сработает, по крайней мере, в C++. Вы могли сохранить указатель в другом месте, прежде чем поместить его в интеллектуальный указатель. Кроме того, легко (но не рекомендуется) получить необработанный указатель C обратно из интеллектуального указателя, выполнив & * smart_ptr;

Chris Jefferson 21.11.2008 17:29

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

Johannes Schaub - litb 28.11.2008 20:31

Я написал небольшой ответ по поводу алиасинга здесь: stackoverflow.com/questions/270408/…

Johannes Schaub - litb 28.11.2008 20:32

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

MSalters 02.12.2008 18:20

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

Если вам просто нужен указатель на "автоудаление", есть много злонамеренного auto_ptr или новый и блестящий (но пока не очень поддерживаемый) unique_ptr из C++ 0x.

Когда я последний раз тестировал VC6, компилятор не смог оптимизировать код с помощью интеллектуального указателя так же хорошо, как с помощью необработанного указателя. С тех пор все могло измениться.

Когда я последний раз тестировал старую версию boost (кажется, 1.34) с VC6, компилятор оптимизировал атомарное приращение refcount для weak_ptr. Это значительно ускорило работу, хотя и вызвало довольно много сбоев в многопоточных библиотеках.

Michel 25.11.2008 23:17

Я понимаю, что VC6 по-прежнему активно используется в крупных проектах, которые нелегко переключить, но давайте будем честными: он не был зрелым компилятором до VC2003, второго выпуска в жизненном цикле продукта VS.NET.

ApplePieIsGood 12.12.2008 23:10

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

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

Часто упускается из виду промежуточный вариант между std::vector<T*>, управляемым «вручную» (то есть необработанными указателями) и std::vector<boost::shared_ptr<T> >, в форме классов boost::ptr_container.

Они сочетают в себе производительность контейнера необработанных указателей с удобством контейнера интеллектуальных указателей (т. Е. Они обеспечивают функциональность, которую люди хотели бы предоставить в контейнерах STL std::auto_ptr, если бы это сработало).

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