Различия между уникальным ptr и общим ptr [дубликат]


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

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

4 170

4 ответа:

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

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

unique_ptr<T> myPtr(new T);       // Okay
unique_ptr<T> myOtherPtr = myPtr; // Error: Can't copy unique_ptr
, unique_ptr может быть двигался использование новой семантики перемещения:
unique_ptr<T> myPtr(new T);                  // Okay
unique_ptr<T> myOtherPtr = std::move(myPtr); // Okay, resource now stored in myOtherPtr

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

unique_ptr<T> MyFunction() {
    unique_ptr<T> myPtr(/* ... */);

    /* ... */

    return myPtr;
}

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

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

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

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

короче:

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

надеюсь, что это помогает!

unique_ptr Это легкий умный указатель выбора, если у вас просто есть динамический объект где-то, для которого один потребитель имеет единственную (следовательно, "уникальную") ответственность-возможно, класс-оболочка, который должен поддерживать некоторый динамически выделенный объект. unique_ptr имеет очень мало накладных расходов. Он не копируется,но перемещается. Его тип и template <typename D, typename Deleter> class unique_ptr;, Так что это зависит от два параметры шаблона.

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

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

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

но есть еще одна большая разница: общий тип указателей всегдаtemplate <typename T> class shared_ptr;, и это несмотря на то, что вы можете инициализировать его с помощью пользовательских удалителей и С пользовательских распределителей. Удалитель и распределитель отслеживаются с помощью стирания типа и отправки виртуальной функции, что добавляет к внутреннему весу класса, но имеет огромное преимущество, что различные виды общих указателей типа 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, то сохраненный объект будет уничтожен.