В чем разница между следующим набором указателей? Когда вы используете каждый указатель в рабочем коде, если вообще?
Примеры будут оценены!
scoped_ptr
shared_ptr
weak_ptr
intrusive_ptr
Вы используете повышение в производственном коде?
источник
В чем разница между следующим набором указателей? Когда вы используете каждый указатель в рабочем коде, если вообще?
Примеры будут оценены!
scoped_ptr
shared_ptr
weak_ptr
intrusive_ptr
Вы используете повышение в производственном коде?
Это легко, когда у вас есть свойства, которые вы можете назначить каждому умному указателю. Есть три важных свойства.
Первый означает, что умный указатель не может удалить объект, потому что он ему не принадлежит. Второе означает, что только один умный указатель может одновременно указывать на один и тот же объект. Если интеллектуальный указатель должен быть возвращен из функций, владение передается, например, возвращенному интеллектуальному указателю.
Третий означает, что несколько интеллектуальных указателей могут указывать на один и тот же объект одновременно. Это относится и к необработанному указателю , однако у необработанных указателей отсутствует важная особенность: они не определяют, являются ли они собственниками или нет. Интеллектуальный указатель доли владения удалит объект, если каждый владелец откажется от объекта. Такое поведение часто требуется, поэтому умные указатели с общим доступом широко распространены.
Некоторые владельцы умных указателей не поддерживают ни второе, ни третье. Поэтому они не могут быть возвращены из функций или переданы куда-либо еще. Что наиболее подходит для RAII
целей, где интеллектуальный указатель хранится локально и просто создается, так что он освобождает объект после того, как он выходит из области видимости.
Доля владения может быть реализована с помощью конструктора копирования. Это естественно копирует умный указатель, и копия, и оригинал будут ссылаться на один и тот же объект. Передача права собственности в настоящее время не может быть реализована в C ++, потому что нет средств для передачи чего-либо из одного объекта в другой, поддерживаемых языком: если вы пытаетесь вернуть объект из функции, то происходит то, что объект копируется. Таким образом, умный указатель, который реализует передачу права собственности, должен использовать конструктор копирования для реализации этой передачи права собственности. Однако это, в свою очередь, нарушает его использование в контейнерах, поскольку требования определяют определенное поведение конструктора копирования элементов контейнеров, которое несовместимо с этим так называемым поведением «движущегося конструктора» этих интеллектуальных указателей.
C ++ 1x обеспечивает встроенную поддержку передачи права собственности, вводя так называемые «конструкторы перемещения» и «операторы назначения перемещения». Он также поставляется с таким интеллектуальным указателем передачи права собственности unique_ptr
.
scoped_ptr
это умный указатель, который не может быть передан или разделен Это просто полезно, если вам нужно локально выделить память, но убедитесь, что она освобождается снова, когда выходит из области видимости. Но он все еще может быть заменен другим scoped_ptr, если вы хотите это сделать.
shared_ptr
это умный указатель, который разделяет владение (третий вид выше). Он подсчитывает ссылки, поэтому он может видеть, когда последняя его копия выходит из области видимости, а затем освобождает управляемый объект.
weak_ptr
является не владеющим умным указателем. Он используется для ссылки на управляемый объект (управляемый shared_ptr) без добавления счетчика ссылок. Обычно вам нужно получить необработанный указатель из shared_ptr и скопировать его. Но это было бы небезопасно, поскольку у вас не было бы способа проверить, когда объект был фактически удален. Таким образом, weak_ptr предоставляет средства, ссылаясь на объект, управляемый shared_ptr. Если вам нужен доступ к объекту, вы можете заблокировать управление им (чтобы избежать того, что в другом потоке shared_ptr освобождает его при использовании объекта), а затем использовать его. Если слабый_птр указывает на уже удаленный объект, он заметит вас, выдав исключение. Использование weak_ptr наиболее полезно, когда у вас есть циклическая ссылка: подсчет ссылок не может легко справиться с такой ситуацией.
intrusive_ptr
похож на shared_ptr, но он не хранит счетчик ссылок в shared_ptr, но оставляет увеличение / уменьшение счетчика некоторым вспомогательным функциям, которые должны быть определены управляемым объектом. Это имеет то преимущество, что уже ссылочный объект (который имеет счетчик ссылок, увеличенный с помощью внешнего механизма подсчета ссылок) может быть вставлен в intrusive_ptr - потому что счетчик ссылок больше не является внутренним по отношению к интеллектуальному указателю, но интеллектуальный указатель использует существующий механизм подсчета ссылок.
unique_ptr
указатель передачи права собственности Вы не можете скопировать его, но вы можете переместить его с помощью конструкторов перемещения C ++ 1x:
unique_ptr<type> p(new type);
unique_ptr<type> q(p); // not legal!
unique_ptr<type> r(move(p)); // legal. p is now empty, but r owns the object
unique_ptr<type> s(function_returning_a_unique_ptr()); // legal!
Это семантика, которой придерживается std :: auto_ptr, но из-за отсутствия встроенной поддержки перемещения она не может обеспечить их без ошибок. unique_ptr автоматически украдет ресурсы из временного другого unique_ptr, который является одной из ключевых особенностей семантики перемещения. auto_ptr будет устаревшим в следующем выпуске C ++ Standard в пользу unique_ptr. C ++ 1x также позволит вставлять объекты, которые являются только подвижными, но не копируемыми в контейнеры. Так что вы можете, например, втиснуть unique_ptr в вектор. Я остановлюсь здесь и напишу вам хорошую статью об этом, если вы хотите узнать больше об этом.
auto_ptr
уже устарело (C ++ 11).intrusive_ptr
может быть предпочтительнееshared_ptr
для лучшей согласованности кэша. Очевидно, что кэш работает лучше, если вы храните счетчик ссылок как часть памяти самого управляемого объекта вместо отдельного объекта. Это может быть реализовано в шаблоне или суперклассе управляемого объекта.scoped_ptr является самым простым. Когда он выходит за рамки, он уничтожается. Следующий код недопустим (scoped_ptrs не подлежит копированию), но проиллюстрирует это:
shared_ptr является подсчетом ссылок. Каждый раз, когда происходит копирование или присвоение, счетчик ссылок увеличивается. Каждый раз, когда запускается деструктор экземпляра, счетчик ссылок для необработанного T * уменьшается. Если значение равно 0, указатель освобождается.
weak_ptr - это слабая ссылка на разделяемый указатель, которая требует от вас проверки того, существует ли указанная shared_ptr
intrusive_ptr обычно используется, когда требуется сторонний смарт-ptr. Он вызовет бесплатную функцию для добавления и уменьшения счетчика ссылок. См. Ссылку, чтобы увеличить документацию для получения дополнительной информации.
источник
if (tPtrAccessed[0].get() == 0)
должно бытьif (tPtrAccessed.get() == 0)
?Не забывайте
boost::ptr_container
ни в одном обзоре повышения умных указателей. Они могут быть неоценимы в ситуациях, когда, напримерstd::vector<boost::shared_ptr<T> >
, будет слишком медленно.источник
Я второй совет о просмотре документации. Это не так страшно, как кажется. И несколько коротких намеков:
scoped_ptr
- указатель автоматически удаляется, когда он выходит из области видимости. Примечание - назначение невозможно, но не вносит накладных расходовintrusive_ptr
указатель подсчета ссылок без накладных расходовsmart_ptr
. Однако сам объект хранит счетчик ссылокweak_ptr
- работает вместе с тем,shared_ptr
чтобы справляться с ситуациями, приводящими к циклическим зависимостям (прочитайте документацию и поищите в Google красивую картинку;)shared_ptr
- общие, самые мощные (и тяжелые) из умных указателей (из предложенных boost)auto_ptr
, который гарантирует, что объект, на который он указывает, автоматически уничтожается, когда управление покидает область видимости. Однако у него другая семантика копирования, чем у остальных парней.unique_ptr
- придет с C ++ 0xОтвет на редактирование: Да
источник