Подтвердить что ты не робот

Накладные расходы и реализация использования shared_ptr

Краткое введение: Я работаю над многопоточным кодом, и мне приходится делиться динамически выделенными объектами между двумя потоками. Чтобы сделать мой код более чистым (и менее подверженным ошибкам), я хочу явно "удалить" объекты в каждом потоке и поэтому хочу использовать shared_ptr.

Первый вопрос:

Я хочу знать, есть ли в реализации -> operator в shared_ptr дополнительные дополнительные служебные данные (например, более крупные, чем unique_ptr) во время выполнения. Объекты, о которых я говорю, обычно экземпляры longlife копируются только один раз после создания (когда я распространяю их между потоками), тогда я получаю доступ только к этим методам и полям этих объектов.

Я знаю, что shared_ptr защищает только подсчет ссылок.

Второй вопрос:

Насколько оптимизированы shared_ptr в libstdС++? Всегда ли он использует мьютекс или использует атомные операции (я сосредоточен на платформах x86 и ARM)?

4b9b3361

Ответ 1

Первый вопрос: используя operator->

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

Второй вопрос: mutex/atomics

Я ожидаю, что libstdС++ будет использовать Atomics на платформе x86, будь то стандартные средства или специфические свойства g++ (в старых версиях). Я считаю, что реализация Boost уже сделала это.

Я не могу, однако, прокомментировать ARM.

Примечание: С++ 11, представляющий семантику перемещения, многие экземпляры естественно избегают использования shared_ptr.

Примечание: прочитайте о правильном использовании shared_ptr здесь, вы можете использовать ссылки на shared_ptr (const или нет), чтобы избежать большей части копий/разрушение в целом, поэтому их производительность не слишком важна.

Ответ 2

GCC shared_ptr не использует блокировку или атомацию в однопоточном коде. В многопоточном коде он будет использовать атомарные операции, если атомная команда сравнения и замены поддерживается процессором, в противном случае счетчики ссылок защищены мьютексом. На i486 и позже он использует атоматику, i386 не поддерживает cmpxchg, поэтому использует реализацию на основе mutex. Я полагаю, что ARM использует атоматику для архитектуры ARMv7 и позже.

(То же самое относится как к std::shared_ptr, так и к std::tr1::shared_ptr.)