"Если требуется работа с голой памятью", - в c++ обычно не работают с голой памятью (free store). Работают с объектами, у которых есть
время жизни. Мы выделяем память посредством низкоуровневых функций, только чтобы потом в ней создавать живые объекты, например с помощью placement new.
В этом смысле подход "без использования векторов и прочего" не имеет совершенно никакого значения. Как руками мы выделяем память и создаем в ней объекты, так поступает и вектор. Но только вектор позволяет нам сохранить здоровыми несколько клеток головного мозга. Другие аргументы в
соответствующем разделе super-faq по ключевому слову vector.
"например, какое-то апи требует тип T *" -
vector<T>::data()
.
Идиоматичность кода подразумевает использование актуальных стандартных средств языка. Оба примера напоминают c++03. Если код плохо читаем как в первом примере, то имеет смысл поискать лучшие альтернативы. Если их нет, то завернуть код во что-нибудь удобочитаемое, вектор например. Про идиоматичную низкоуровневую работу с памятью можно почитать у Страуструпа в примере реализации вектора.
Вопрос оптимизации - отдельная тема. Оптимизация под конкретные нужды не обязана быть идиоматичной или в принципе соответствовать общим представлениям. Например, вместо хранения массива структур, мы можем создать и использовать отдельно массивы полей структур. Можете поискать информацию по data-oriented design.