Подтвердить что ты не робот

Unique_ptr - значительное улучшение?

В реальном стандарте С++ создание коллекций, удовлетворяющих следующим правилам, сложно, если не невозможно:

  • безопасность исключений,
  • дешевые внутренние операции (в реальных контейнерах STL: операции - это копии),
  • автоматическое управление памятью.

Чтобы удовлетворить (1), коллекция не может хранить исходные указатели. Чтобы удовлетворить (2), коллекция должна хранить необработанные указатели. Чтобы удовлетворить (3), коллекция должна хранить объекты по значению.

Заключение: три элемента конфликтуют друг с другом.

Элемент (2) не будет удовлетворен, если shared_ptr используется, потому что, когда сборке нужно будет перемещать элемент, ему нужно будет сделать два вызова: конструктору и деструктору. Нет массивных, memcpy() -подобных операций копирования/перемещения.

Правильно ли, что описанная проблема будет решена с помощью unique_ptr и std::move()? Коллекции, использующие инструменты, смогут удовлетворить все 3 условия:

  • Когда коллекция будет удалена как побочный эффект исключения, она вызовет деструкторы unique_ptr. Нет утечки памяти.
    • unique_ptr не требуется дополнительное пространство для счетчика ссылок; поэтому его тело должно быть точно того же размера, что и обернутый указатель,
    • Я не уверен, но похоже, что это позволяет перемещать группы unique_ptrs с помощью memmove() подобных операций (?),
    • даже если это невозможно, оператор std::move() позволяет перемещать каждый объект unique_ptr, не создавая пары пары конструктор/деструктор.
  • unique_ptr будет иметь эксклюзивное право владения данной памятью. Никаких случайных утечек памяти не будет.

Это правда? Каковы другие преимущества использования unique_ptr?

4b9b3361

Ответ 1

Я полностью согласен. Наконец, естественный способ обработки выделенных кучей объектов.

В ответ на:

Я не уверен, но похоже, что это позволяет перемещать группы unique_ptr с помощью memmove() подобных операций,

для этого было , но оно не попало в стандарт С++ 11.

Ответ 2

Да, вы правы. Я бы добавил, что это возможно благодаря r-значениям ссылок.

Ответ 3

Когда коллекция будет удалена как побочный эффект исключения, она вызовет destructors unique_ptr. Нет утечки памяти.

Да, контейнер unique_ptr удовлетворит это.

unique_ptr не требует дополнительного места для счетчика ссылок; поэтому его тело должно быть точно того же размера, что и обернутый указатель

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

Я не уверен, но похоже, что это позволяет перемещать группы unique_ptrs, используя memmove() как операции (?),

Абсолютно нет. unique_ptr не является тривиальным классом; поэтому он не может быть memmove d вокруг. Даже если это так, вы не можете просто memmove их, потому что нужно вызвать деструкторы для оригиналов. Это должно быть memmove, за которым следует memset.

даже если это невозможно, оператор std:: move() позволяет перемещать каждый объект unique_ptr, не делая пары-пары конструктора/деструктора.

Также неверно. Движение не приводит к тому, что конструкторы и деструкторы не будут вызваны. Уничтожаемые unique_ptr должны быть уничтожены; что требует вызова их деструкторов. Аналогично, новый unique_ptr должен иметь свои конструкторы; как начинается срок жизни объекта.

Там не избежать этого; это как работает С++.

Однако, это не то, о чем вам следует беспокоиться. Честно говоря, если вас беспокоит простой вызов конструктора/деструктора, вы либо находитесь в коде, который вам следует оптимизировать вручную (и, таким образом, писать свой собственный код), либо вы преждевременно оптимизируете свой код. Важно то, что вызываются конструкторы/деструкторы; важно, как быстро получается полученный код.

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

Да, это будет.

Лично я бы сказал, что вы делаете одно из следующих действий:

  • Быть чрезмерно параноидальным относительно копирования объектов. Это свидетельствует о том, что вы считаете, что положить shared_ptr в контейнер слишком дорого из копии. Это слишком распространенная болезнь среди программистов на C++. Это не означает, что копирование всегда хорошо или что-то в этом роде, но одержимость над копированием shared_ptr в контейнере смехотворна вне исключительных обстоятельств.

  • Не знаю, как правильно использовать семантику перемещения. Если ваши объекты дорого копировать, но дешево перемещать... затем переместите их в контейнер. Там нет причин иметь указатель, если ваши объекты уже содержат указатели. Просто используйте движение с самими объектами, а не unique_ptr для объектов.

  • Без учета альтернатив. А именно, Boost указательные контейнеры. Кажется, у них есть все, что вы хотите. Они имеют указатели на свои объекты, но внешне они имеют семантику значений, а не семантику указателя. Они безопасны, и любое копирование происходит с указателями. Нет unique_ptr конструктор/деструктор "служебные данные".

Ответ 4

Похоже, что три условия, которые я перечислял в своем сообщении, можно получить, используя Boost Pointer Container Library.

Ответ 5

Этот вопрос раздражает, почему я так люблю сборщик мусора Boehm (libgc). Никогда не нужно копировать что-либо по причинам управления памятью, и, действительно, владение памятью больше не нужно упоминать как часть API. Вы должны купить немного больше оперативной памяти, чтобы получить такую ​​же производительность процессора, но вы сэкономите сотни часов времени программистов. Вы решаете.