Что сейчас используется для динамического выделения памяти?

Рейтинг: 5Ответов: 3Опубликовано: 21.04.2023

Просматривал группу в Телеграме, там было вот такое сообщение по поводу, что NULL можно безопасно удалять. Банальщина, но вот в обсуждении люди начали писать, что уже давно никто в С++ не использует new/delete, и даже placement-new - ненужная фича.

Я до такой степени отстал от жизни? Как лучше всего динамически выделять новые объекты в современном С++? Какую технологию использовать? Чем placement-new лучше обычного new (мне кажется, возни только больше).

Если не тяжело, не закрывайте как "невозможно дать объективный ответ" :)

Ответы

▲ 6Принят

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

struct dlist {
  dlist * prev ;
  dlist * next ;
} ;

А инициализировать объект, который ещё не в неопределённом состоянии можно только с placement-new. Например, которые в union :

class A {};
class B {};
struct st {
  int type ; // A or B
  union {
    A a ;
    B b ;
  } ;
} x ;
...
new ( & x . b ) B { } ;

В C++20 появился construct_at, но это не замена, а ещё одна обёртка для отсроченной инициализации constexpr объекта.

▲ 8

уже давно никто в С++ не использует new/delete

Их используют только внутри кода контейнеров и умных указателей. (В идеальном мире.) Которые желательно использовать готовые, а не костылить свои.

За ручной вызов new/delete (вместо использования контейнера или умного указателя) нужно бить по рукам.


А начинка внутри контейнеров/ умных указателей уже давно принципиально не менялась. Там как были new/delete, так и остались.

Чем placement-new лучше обычного new (мне кажется, возни только больше).

Он для других целей. Например, его использует std::variant. Или std::vector, чтобы выделить память заранее, а объекты в ней создать потом.

▲ 2

В бизнес логике почти никогда не надо использовать голые new/delete. Достаточно make_unique/make_shared и готовых контейнеров. Но если вам надо самому реализовать контейнер (временные ограничения или время компиляции), использовать union (например, для алгебраических типов), или написать что-то низкоуровневое/freestanding (например, на некоторых платформах нет <new> или <memory>, что уж говорить про <vector>), то тогда без них не обойтись.

Чем placement-new лучше обычного new (мне кажется, возни только больше)?

Это разные вещи, new вызывает глобальную функцию для аллокации, placement new пишет уже в выделенную ранее (если вы не забыли) память. Часто вместо последнего удобней использовать PMR.