Pull to refresh

Comments 11

Очень интересный пост! Спасибо большое за подробное описание применения этого контейнера, возможных ошибок и новых методов.

Пока что не могу придумать случаев, когда такой контейнер я бы мог использовать. Будто бы можно обойтись массивом и вручную считать необходимые индексы и размеры.

Разве что работа с итераторами упростится при использовании этого контейнера.

Ну например если мы знаем что элементов может быть не больше чем N, но не знаем сколько именно, и динамические аллокации делать не хочется.

Вектор имеет размер и емкость. Тут речь про статическкую емкость, а размер как раз может меняться. Для std::vector ближайшим аналогом будет, если вы изначальное сделаете reserve и при добавлении элементов сами будете следить чтобы size() не превышал capacity(). Но std::vector память выделит в куче.

Лично мне не хватает гибридного варианта - вектора со статическим буфером на N элементов, но переходящий на динамическую аллокацию при превышении размера буфера.

Полезно, когда известно, что в 99% случаев алгоритм работает с небольшим числом элементов, но иногда может прилететь что-то большое.

Да, есть small object optimization, но он, во-первых, не гарантирован, во-вторых, им нельзя управлять (а оптимальное значение N может отличаться от алгоритма к алгоритму).

Такое есть в библиотеке Abseil и зовётся InlinedVector.

Аналогичная хотелка для std::any, который тоже имеет динамически выделяемый буфер и опять же во многих задачах можно прикинуть "большую часть времени нам приходят объекты размером не более N, где N очень специфичен для задачи".

Есть ли где-то такое, мне неизвестно.

Такое есть в библиотеке Abseil и зовётся InlinedVector.

Есть также small_vector в boost, может когда-нибудь и его добавят в STL.

То что вы хотите, называется "small vector" pattern.

  • В LLVM есть SmallVector - именно оно самое.

  • Есть в Boost container::small_vector.

Можно наколхозить самому на std::pmr::vector из C++17, передав ему std::pmr::monotonic_buffer_resource или (un)synchronized_pool_resource, в конструктор конторого передать буфер на стеке. Как только закончится capacity, то такой вектор полезет аллоцировать память в куче.

как обычно, потребность навалить побольше 💩 в стандарт, чтобы оттолкнуть еще больше старых пользователей C++

Не так давно я написал в комитет WG21 с предложением добавить в std::vector новую функцию reset(). Она как бы должна была сбрасывать размер массива, чтобы на следующем кадре добавить элементы на те же места, типо как clear(), но сильно быстрее. Это было бы очень полезно если программа работает как ImGui, то есть в Immediate Mode, как было в моëм случае. Но очевидно меня погнали куда подальше с такими предложениями, потому что это вгоняет массив в неопределëнное состояние, что может быть критично.

Но я в целом не жалуюсь, в любом случае, эту функцию я взял из своего динамического массива FE2D::dynamic_array и там всё работает как надо 😉

Sign up to leave a comment.

Articles