Различия между unique_ptr и shared_ptr

Возможные дубликаты:
pimpl: shared_ptr или unique_ptr
умные указатели (boost) объяснили

Может ли кто-нибудь объяснить различия между shared_ptr и unique_ptr?

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

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

 unique_ptr myPtr(new T); // Okay unique_ptr myOtherPtr = myPtr; // Error: Can't copy unique_ptr 

Однако unique_ptr можно перемещать с помощью новой семантики перемещения:

 unique_ptr myPtr(new T); // Okay unique_ptr myOtherPtr = std::move(myPtr); // Okay, resource now stored in myOtherPtr 

Аналогично, вы можете сделать что-то вроде этого:

 unique_ptr MyFunction() { unique_ptr myPtr(/* ... */); /* ... */ return myPtr; } 

Эта идиома означает «Я возвращаю вам управляемый ресурс. Если вы явно не зафиксируете возвращаемое значение, тогда ресурс будет очищен. Если вы это сделаете, у вас теперь будет эксклюзивное владение этим ресурсом». Таким образом, вы можете думать о unique_ptr как о более безопасной, лучшей замене для auto_ptr .

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

 shared_ptr myPtr(new T); // Okay shared_ptr myOtherPtr = myPtr; // Sure! Now have two pointers to the resource. 

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

Вкратце:

  1. Используйте unique_ptr если вам нужен один указатель на объект, который будет восстановлен, когда этот единственный указатель будет уничтожен.
  2. Используйте shared_ptr если вам нужно указать несколько указателей на один и тот же ресурс.

Надеюсь это поможет!

unique_ptr – легкий интеллектуальный указатель выбора, если у вас есть только динамический объект, для которого у одного потребителя есть единственная (следовательно, «уникальная») ответственность – возможно, class-shell, который должен поддерживать некоторый динамически выделенный объект. unique_ptr очень мало накладных расходов. Он не копируется, а движимый. Его тип – это template class unique_ptr; , поэтому он зависит от двух параметров шаблона.

unique_ptr также то, что auto_ptr хотел быть в старом C ++, но не мог из-за ограничений этого языка.

shared_ptr с другой стороны, совсем другое животное. Очевидное различие заключается в том, что у вас может быть много потребителей, разделяющих ответственность за динамический объект (следовательно, «общий»), и объект будет уничтожен только тогда, когда все общие указатели исчезнут. Кроме того, вы можете наблюдать слабые указатели, которые будут разумно информированы, если общий указатель, за которым они следуют, исчез.

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

Но есть еще одна большая разница: тип общих указателей всегда является template class shared_ptr; , и это несмотря на то, что вы можете инициализировать его с помощью пользовательских удалений и с помощью пользовательских распределителей. Делектор и распределитель отслеживаются с помощью стирания стилей и отправки виртуальных функций, что добавляет к внутреннему весу classа, но имеет огромное преимущество в том, что различные типы общих указателей типа T являются совместимыми, независимо от сведений о делеции и распределении. Таким образом, они действительно выражают концепцию «совместной ответственности за T », не обременяя потребителя деталями!

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

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

shared_ptr
является умным указателем для совместного использования. Он является одновременно возможностью copyable и movable . Несколько экземпляров интеллектуальных указателей могут владеть одним и тем же ресурсом. Как только последний умный указатель, владеющий ресурсом, выходит из сферы действия, ресурс будет освобожден.

При упаковке указателя в unique_ptr вы не можете иметь несколько копий unique_ptr . В shared_ptr имеется счетчик ссылок, который подсчитывает количество копий сохраненного указателя. Каждый раз, когда копируется shared_ptr , этот счетчик увеличивается. Каждый раз, когда shared_ptr разрушается, этот счетчик уменьшается. Когда этот счетчик достигнет 0, тогда сохраненный объект будет уничтожен.

  • Почему я могу изменить локальную константную переменную с помощью указателей, но не глобальную в C?
  • Разница указателей / адресов
  • Как сделать буквенный * int64 в Go?
  • Что такое «->» в Objective C?
  • Почему для нулевого указателя используется нулевой адрес?
  • Скрытие нулевых значений, понимание того, почему голанг не удается здесь
  • C - Разница между «char var » и «char * var»?
  • Использование fseek с указателем файла, указывающим на stdin
  • Как передать объекты в функции на C ++?
  • Функция не меняет пройденный указатель C ++
  • Какова точка указателей на функции?
  • Interesting Posts

    Как получить список открытых дескрипторов файлов по процессу на C #?

    Любой способ получить ограничительную рамку из объекта three.js Object3D?

    Можно ли подключить беспроводной маршрутизатор к другой точке доступа?

    Использование опций Java 8 с Stream :: flatMap

    Передача данных USB

    Как найти имя контакта с номера телефона на Android?

    Полиморфная привязка модели

    Программное обеспечение для очистки экрана, которое будет перемещаться по страницам

    Имя таблицы как параметр функции PostgreSQL

    Почему #ifndef и #define используются в файлах заголовков C ++?

    Учитывая аудиоstream, найдите, когда дверь хлопает (расчет уровня звукового давления?)

    Компьютерные звуки, а не музыка в наушники и компьютерный динамик одновременно?

    Есть ли браузер, который позволяет различным экземплярам, ​​которые не используют один и тот же файл cookie для одного и того же сайта?

    Ошибка: конфликт с зависимостью «com.google.code.findbugs: jsr305»

    Как получить вывод ассемблера из источника C / C ++ в gcc?

    Давайте будем гением компьютера.