уникальный ПТР-серьезное улучшение?
В реальном стандарте C++ создание коллекций, удовлетворяющих следующим правилам, является трудным, если не невозможным:
- безопасность исключений,
- дешевые внутренние операции (в реальных контейнерах STL: операции являются копиями), Автоматическое управление памятью.
Чтобы удовлетворить (1), коллекция не может хранить необработанные указатели. Чтобы удовлетворить (2), коллекция должна хранить необработанные указатели. Чтобы удовлетворить (3), коллекция должна хранить объекты по значению.
Заключение: эти три пункта противоречат друг другу.
Item (2) не будет удовлетворен при использовании shared_ptr
s, потому что, когда коллекции нужно будет переместить элемент, ей нужно будет сделать два вызова: конструктора и деструктора. Никакие массивные, memcpy()
-подобные операции копирования/перемещения невозможны.
unique_ptr
и std::move()
? Коллекции, использующие инструменты, смогут удовлетворять всем 3 условиям:
- когда коллекция будет удаленный как побочный эффект исключения, он вызовет деструкторы
unique_ptr
. Никакой утечки памяти. -
-
unique_ptr
не нуждается в дополнительном пространстве для счетчика ссылок; поэтому его тело должно быть точно такого же размера, как и завернутый указатель, - я не уверен, но похоже, что это позволяет перемещать группы
unique_ptrs
с помощьюmemmove()
подобных операций (?), - даже если это невозможно, оператор
std::move()
позволит перемещать каждый объектunique_ptr
, не делая вызовы пары конструктор / деструктор.
-
-
unique_ptr
будет иметь исключительное право собственности на данную память. Никаких случайных утечек памяти не будет.
Это правда? Каковы другие преимущества использования unique_ptr
?
5 ответов:
Я полностью согласен. Наконец-то появился естественный способ обработки объектов, выделенных кучей.
В ответ на:
Я не уверен, но похоже, что это позволяет перемещать группы
unique_ptr
s с помощьюmemmove()
подобных операций,Было предложение разрешить это, но оно не вошло в стандарт C++11.
Когда коллекция будет удалена как побочный эффект исключения, она вызовет деструкторы unique_ptr. Никакой утечки памяти.
Да, контейнер
unique_ptr
удовлетворит этому.Unique_ptr не нуждается в дополнительном пространстве для счетчика ссылок, поэтому его тело должно быть точно такого же размера, как и завернутый указатель
unique_ptr
'размер s определяется реализацией. В то время как все разумные реализацииunique_ptr
используют его деструктор по умолчанию скорее всего, будет только указатель по размеру, нет никакой гарантии этого в стандарте.Я не уверен, но похоже, что это позволяет перемещать группы unique_ptrs с помощью memmove (), как операции (?),
Абсолютно нет.
unique_ptr
не является тривиальным классом; поэтому он не может бытьmemmove
d вокруг. Даже если бы это было так, вы не можете простоmemmove
их, потому что деструкторы для оригиналов должны быть вызваны. Это должно бытьmemmove
, за которым следуетmemset
.Даже если это невозможно, оператор std::move () позволит перемещать каждый объект unique_ptr без вызова пары конструктор/деструктор.
Тоже неверно. Движение не заставляет конструкторов и деструкторов не вызываться. Уничтожаемые объекты
unique_ptr
должны быть уничтожены ; это требует вызова их деструкторов. Аналогично, новыеunique_ptr
s должны иметь свои конструкторы, вызываемые; таково время жизни объекта начинает.Этого не избежать; именно так работает C++.
Однако это не то, о чем вам следует беспокоиться. Честно говоря, если вас беспокоит простой вызов конструктора/деструктора, вы либо находитесь в коде, который вы должны оптимизировать вручную (и таким образом писать свой собственный код), либо вы преждевременно оптимизируете свой код. Важно не то, вызываются ли конструкторы/деструкторы, а то, насколько быстр результирующий код.Unique_ptr будет иметь исключительное право собственности на данную память. Никаких случайных утечек памяти не будет.
Да, это будет.
Лично я бы сказал, что вы делаете одно из следующих действий:
Быть чрезмерно параноидальным в отношении копирования объектов. Об этом свидетельствует тот факт, что вы считаете, что помещать
shared_ptr
в контейнер слишком дорого для копии. Это очень распространенная болезнь среди программистов на C++. Это не значит, что копирование всегда хорошо или что-то еще, но одержимость чрезмерное копированиеshared_ptr
в контейнер нелепо вне исключительных обстоятельств.Не знает, как правильно использовать семантику перемещения. Если ваши объекты дорогие для копирования, но дешевые для перемещения... затем переместите их в контейнер. Нет никакой причины иметь косвенный указатель, когда ваши объекты уже содержат косвенный указатель. Просто используйте движение с самими объектами, а не
unique_ptr
s к объектам.Игнорируя альтернативы. Именно, контейнеры указателей Boost . Кажется, у них есть все, что вы хотите. Они владеют указателями на свои объекты, но внешне они имеют семантику значения, а не семантику указателя. Они безопасны для исключений, и любое копирование происходит с указателями. Нет
unique_ptr
конструктор / деструктор "накладные расходы".
Похоже, что три условия, которые я перечислил в своем посте, можно получить с помощью Boost Pointer Container Library .
Этот вопрос плохо объясняет, почему я так люблю Boehm garbage collector (libgc). Никогда нет необходимости копировать что-либо по причинам управления памятью, и действительно, владение памятью больше не должно упоминаться как часть API. Вы должны купить немного больше оперативной памяти, чтобы получить ту же производительность процессора, но вы экономите сотни часов времени программистов. Тебе решать.