Lite_stream
@Lite_stream

Является ли такой способ выделения массива объектов на хипе идиоматичным?

Если требуется работа с голой памятью (например, какое-то апи требует тип T *), без использования векторов и прочего, является ли такой способ создания элементов массива на куче предпочтительным:

Point * points = reinterpret_cast<Point *>(new (std::align_val_t(alignof(Point))) std::byte[SIZE * sizeof(Point)]);


Перед таким:
Point ** points = new Point*[SIZE];

Ведь во мало того, что во втором случае придётся SIZE раз обращаться к аллокатору, так ещё и каждый элемент будет в рандомном месте на хипе (плохо по кэшу), в то время, как в 1-м случае все элементы будут лежать подряд в памяти

P.S.: Point не полиморфный объект
Хотя, если бы Point был полиморфный и максимальный размер ребёнка был бы < CACHE_LINE_SIZE хотя бы раза в 3-4, то можно было бы и в таком случае разместить их всех в массиве с константным смещением равным максимальному размеру ребенка, по идее быстрее бы работало
  • Вопрос задан
  • 171 просмотр
Решения вопроса 1
@code_panik
"Если требуется работа с голой памятью", - в c++ обычно не работают с голой памятью (free store). Работают с объектами, у которых есть время жизни. Мы выделяем память посредством низкоуровневых функций, только чтобы потом в ней создавать живые объекты, например с помощью placement new.

В этом смысле подход "без использования векторов и прочего" не имеет совершенно никакого значения. Как руками мы выделяем память и создаем в ней объекты, так поступает и вектор. Но только вектор позволяет нам сохранить здоровыми несколько клеток головного мозга. Другие аргументы в соответствующем разделе super-faq по ключевому слову vector.

"например, какое-то апи требует тип T *" - vector<T>::data().

Идиоматичность кода подразумевает использование актуальных стандартных средств языка. Оба примера напоминают c++03. Если код плохо читаем как в первом примере, то имеет смысл поискать лучшие альтернативы. Если их нет, то завернуть код во что-нибудь удобочитаемое, вектор например. Про идиоматичную низкоуровневую работу с памятью можно почитать у Страуструпа в примере реализации вектора.

Вопрос оптимизации - отдельная тема. Оптимизация под конкретные нужды не обязана быть идиоматичной или в принципе соответствовать общим представлениям. Например, вместо хранения массива структур, мы можем создать и использовать отдельно массивы полей структур. Можете поискать информацию по data-oriented design.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@res2001
Developer, ex-admin
Можно использовать std::malloc вместо new.
Если класс полиморфный, то можно предварительно вычислять max из размеров всех детей и использовать это значение для выделения массива. Список детей должен быть заранее известен.
Ответ написан
А в чём проблема использовать вектор? Из вектора же можно получить указатель на начальную точку и выделить заранее нужное количество места.
А вот эта простыня с reinterpret_cast вообще не очевидная
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы