умные указатели (boost) объяснили

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

Примеры были бы оценены!

  1. scoped_ptr

  2. shared_ptr

  3. weak_ptr

  4. intrusive_ptr

Вы используете boost в производственном коде?

    Основные свойства интеллектуальных указателей

    Это легко, когда у вас есть свойства, которые вы можете назначить каждому умному указателю. Существует три важных свойства.

    • нет собственности вообще
    • передача права собственности
    • доля собственности

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

    Третье означает, что несколько интеллектуальных указателей могут одновременно указывать на один и тот же объект. Это относится и к необработанному указателю , однако у сырых указателей отсутствует важная функция: они не определяют, владеют ли они или нет. Интеллектуальный указатель доли владения удалит объект, если каждый владелец откажется от объекта. Такое поведение часто требуется, поэтому широко распространенные общие интеллектуальные указатели широко распространены.

    Некоторые владеющие интеллектуальными указателями не поддерживают ни вторую, ни третью. Поэтому они не могут быть возвращены из функций или переданы где-то в другом месте. Это наиболее подходит для целей RAII где интеллектуальный указатель хранится локально и только что создан, поэтому он освобождает объект после его выхода из области видимости.

    Доля собственности может быть реализована с помощью конструктора копирования. Это, естественно, копирует умный указатель, и копия, и оригинал будут ссылаться на один и тот же объект. Передача права собственности на настоящий момент не может быть реализована на C ++, поскольку нет средств для передачи чего-либо из одного объекта в другой, поддерживаемого языком. Если вы пытаетесь вернуть объект из функции, то происходит то, что объект копируется. Поэтому умный указатель, который реализует передачу права собственности, должен использовать конструктор копирования для реализации этой передачи права собственности. Однако это, в свою очередь, нарушает его использование в контейнерах, поскольку требования определяют определенное поведение конструктора копирования элементов контейнеров, что несовместимо с этим так называемым «перемещающимся конструктором» поведения этих интеллектуальных указателей.

    C ++ 1x обеспечивает встроенную поддержку передачи права собственности путем введения так называемых «конструкторов перемещения» и «операторов переадресации». Он также поставляется с таким интеллектуальным указателем передачи собственности, который называется unique_ptr .

    Классификация интеллектуальных указателей

    scoped_ptr – это умный указатель, который не может быть передан или недоступен. Он просто полезен, если вам нужно локально выделять память, но убедитесь, что он снова освобожден, когда он выходит из сферы видимости. Но он все равно может быть заменен другим scoped_ptr, если вы хотите это сделать.

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

    weak_ptr – не владеющий интеллектуальным указателем. Он используется для ссылки на управляемый объект (управляемый shared_ptr) без добавления счетчика ссылок. Как правило, вам нужно будет вытащить исходный указатель из shared_ptr и скопировать его. Но это не было бы безопасно, поскольку у вас не было бы возможности проверить, когда объект был фактически удален. Таким образом, weak_ptr предоставляет средства путем ссылки на объект, управляемый shared_ptr. Если вам нужен доступ к объекту, вы можете заблокировать его управление (чтобы избежать этого в другом streamе, shared_ptr освободит его, пока вы используете объект), а затем используйте его. Если weak_ptr указывает на уже удаленный объект, он заметит вас, выставив исключение. Использование weak_ptr наиболее полезно, если у вас есть циклическая ссылка: подсчет ссылок не может легко справиться с такой ситуацией.

    intrusive_ptr подобен shared_ptr, но он не поддерживает счетчик ссылок в shared_ptr, но оставляет приращение / декремент count для некоторых вспомогательных функций, которые должны быть определены объектом, который управляется. Это имеет то преимущество, что объект с уже ссылкой (который имеет счетчик ссылок, увеличенный внешним механизмом подсчета ссылок) может быть забит в intrusive_ptr – поскольку счетчик ссылок больше не является внутренним для интеллектуального указателя, но интеллектуальный указатель использует существующую механизм подсчета ссылок.

    unique_ptr – это передача указателя собственности. Вы не можете его скопировать, но вы можете переместить его с помощью конструкторов перемещения C ++ 1x:

     unique_ptr p(new type); unique_ptr q(p); // not legal! unique_ptr r(move(p)); // legal. p is now empty, but r owns the object unique_ptr s(function_returning_a_unique_ptr()); // legal! 

    Это семантика, которой подчиняется std :: auto_ptr, но из-за отсутствия встроенной поддержки для перемещения она не может обеспечить их без ошибок. unique_ptr автоматически украдет ресурсы из временного другого unique_ptr, который является одной из ключевых особенностей семантики перемещения. auto_ptr будет устаревшим в следующем выпуске C ++ Standard в пользу unique_ptr. C ++ 1x также разрешает набивать объекты, которые только перемещаются, но не могут быть скопированы в контейнеры. Таким образом, вы можете использовать unique_ptr в вектор, например. Я остановлюсь здесь и расскажу вам о прекрасной статье об этом, если вы хотите больше узнать об этом.

    scoped_ptr является самым простым. Когда он выходит из сферы действия, он уничтожается. Следующий код является незаконным (scoped_ptrs не копируются), но иллюстрирует точку:

     std::vector< scoped_ptr > tPtrVec; { scoped_ptr tPtr(new T()); tPtrVec.push_back(tPtr); // raw T* is freed } tPtrVec[0]->DoSomething(); // accessing freed memory 

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

     std::vector< shared_ptr > tPtrVec; { shared_ptr tPtr(new T()); // This copy to tPtrVec.push_back and ultimately to the vector storage // causes the reference count to go from 1->2 tPtrVec.push_back(tPtr); // num references to T goes from 2->1 on the destruction of tPtr } tPtrVec[0]->DoSomething(); // raw T* still exists, so this is safe 

    weak_ptr – это слабая ссылка на общий указатель, который требует, чтобы вы проверили, все ли по-прежнему включен параметр shared_ptr

     std::vector< weak_ptr > tPtrVec; { shared_ptr tPtr(new T()); tPtrVec.push_back(tPtr); // num references to T goes from 1->0 } shared_ptr tPtrAccessed = tPtrVec[0].lock(); if (tPtrAccessed[0].get() == 0) { cout << "Raw T* was freed, can't access it" } else { tPtrVec[0]->DoSomething(); // raw } 

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

    Не boost::ptr_container в любом обзоре boost::ptr_container интеллектуальных указателей. Они могут быть неоценимыми в ситуациях, когда например std::vector > будет слишком медленным.

    Я второй совет по поводу просмотра документации. Это не так страшно, как кажется. И несколько коротких подсказок:

    • scoped_ptr – автоматически удаляется указатель при выходе из области видимости. Примечание. Невозможно назначить назначение, но не вводит никаких накладных расходов
    • intrusive_ptr – указатель подсчета ссылок без накладных расходов smart_ptr . Однако сам объект хранит счетчик ссылок
    • weak_ptr – работает совместно с shared_ptr чтобы справиться с ситуациями, приводящими к циклическим зависимостям (прочитайте документацию и выполните поиск в google для хорошего изображения;)
    • shared_ptr – общий, самый мощный (и супертяжелый) умных указателей (от тех, которые предлагают boost)
    • Существует также старый auto_ptr , который гарантирует, что объект, на который он указывает, автоматически уничтожается, когда элемент управления выходит из области. Однако у него есть другая семантика копирования, чем остальные ребята.
    • unique_ptr – будет поставляться с C ++ 0x

    Ответ на редактирование: Да

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