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

Плюсы и минусы умных указателей

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

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

4b9b3361

Ответ 1

Интеллектуальные указатели не помогают избежать циклов в графических структурах.

Например, объект A содержит умный указатель на объект B и объект B - назад к объекту A. Если вы отпустите все указатели на A и B перед отключением A от B (или B от A), оба A и B будут удерживать друг друга и образовывать счастливую утечку памяти.

Сбор мусора может помочь в этом - он может видеть, что оба объекта недоступны и освобождают их.

Ответ 2

Я хотел бы упомянуть ограничения производительности. Умеренные указатели обычно используют атомарные операции (например, InterlockedIncrement в API Win32) для подсчета ссылок. Эти функции значительно медленнее, чем простая целочисленная арифметика.

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

Ответ 3

Это довольно интересно: Smart Pointers.
Это образец главы "Современного дизайна на C++" Андрея Александреску.

Ответ 4

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

Следите за циклами - как уже упоминалось, вам нужны слабые указатели, чтобы сломать циклы. Однако на сложном графике, который не всегда легко сделать.

Слишком большой выбор - большинство библиотек предлагают разные реализации с различными преимуществами/недостатками. К сожалению, в большинстве случаев эти разные варианты несовместимы, что становится проблемой при микшировании библиотек. (скажем, LibA использует LOKI, LibB использует boost). Чтобы запланировать за enable_shared_from_this отстой, нужно решить соглашения об именах между intrusive_ptr, shared_ptr и weak_ptr для связки объектов.


Для меня единственным преимуществом shared_ptr (или одной из подобных функций) является то, что он связан с политикой уничтожения при создании. Оба С++ и Win32 предлагают так много способов избавиться от вещей, что это даже не смешно. Связь во время построения (без влияния на фактический тип указателя) означает, что у меня есть обе политики в одном месте.

Ответ 5

Помимо технических ограничений (уже упомянутых: круговые зависимости), я бы сказал, что самое важное в умных указателях - это помнить, что это все еще обходное решение для удаления объектов, выделенных кучей. Выделение стека - лучший вариант для большинства случаев - наряду с использованием ссылок - для управления временем жизни объектов.

Ответ 6

Вот несколько вещей

  • Нет определенного объекта, который уничтожает объект. Часто желательно точно знать, когда и как разрушается объект.
  • Круговые зависимости. Если они существуют, у вас будет утечка памяти. Обычно, когда weak_ptr приходит на помощь.

Ответ 8

Раймонд Чен, как известно, неоднозначно относится к умным указателям. Есть проблемы с когда деструктор действительно работает (учтите, что деструктор работает в четко определенное время в четко определенном порядке; просто время от времени вы забудете, что он после последней строки в вашей функции).

Также помните, что "умный указатель" - довольно большая категория. Я включаю std::vector в эту категорию (a std::vector по существу является интеллектуальным массивом).

Ответ 9

Возникает проблема с подсчетом ссылок в некоторых типах структур данных, которые имеют циклы. Также могут возникать проблемы с доступом к интеллектуальным указателям из нескольких потоков, одновременный доступ к подсчетам ссылок может вызвать проблемы. Там утилита в boost называется atomic.hpp, которая может смягчить эту проблему.

Ответ 10

Многие люди сталкиваются с проблемами при использовании интеллектуальных указателей, смешанных с необработанными указателями (к тем же объектам). Типичным примером является взаимодействие с API, использующим исходные указатели.
Например; в boost::shared_ptr есть функция .get(), которая возвращает необработанный указатель. Хорошая функциональность при использовании с осторожностью, но многие люди, похоже, путешествуют по ней.
ИМХО это пример "негерметичной абстракции".