С++: безопасно ли работать с std::vectors, как если бы они были массивами?

Мне нужно иметь массив элементов фиксированного размера и вызывать функции, которые требуют знать, как они помещаются в память, в частности:

  • функции, такие как glVertexPointer, должны знать, где находятся вершины, насколько они отдалены друг от друга и т.д. В моем случае вершины будут членами сохраняемых элементов.

  • чтобы получить индекс элемента внутри этого массива, я бы предпочел избегать наличия поля index внутри моих элементов, но скорее играл бы с арифметикой указателей (т.е. индекс Element *x будет x - & array[0]) - Кстати, это звучит грязно для меня: это хорошая практика или я должен делать что-то еще?


Можно ли использовать std::vector для этого?

Что-то заставляет меня думать, что std::array будет более подходящим, но:

  • Конструктор и деструктор для моей структуры будут редко вызываться: я не возражаю против таких накладных расходов.

  • Я собираюсь установить размер std::vector для размера, который мне нужен (размер, который будет использоваться для std::array, поэтому не будет наноситься накладных расходов из-за спорадического перераспределения.

  • Я не против небольшого накладного расхода для внутренней структуры std::vector.

  • Я мог бы использовать возможность изменять размер вектора (или лучше: иметь размер, выбранный во время установки), и я думаю, что нет никакого способа сделать это с помощью std:: array, так как его размер является параметром шаблона (это слишком плохо: я мог бы это сделать даже со старым C-подобным массивом, просто динамически распределяя его по куче).


Если std::vector отлично подходит для моих целей, я хотел бы узнать подробности, если у него будут некоторые служебные данные времени выполнения по отношению к std::array (или к простому массиву C):

Я знаю, что он вызовет конструктор по умолчанию для любого элемента, когда я увеличу его размер (но, я думаю, это ничего не будет стоить, если мои данные имеют пустой конструктор по умолчанию?), то же самое для деструктора. Что-нибудь еще?

Ответ 1

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

Как указано другими, убедитесь, что вы не перераспределяете вектор, пока используете данные, хранящиеся в нем, если вы используете указатели на элементы (или итераторы) для доступа к нему.

Ответ 2

Хорошо обрабатывать данные в std::vector как массив, получить указатель на начало его с помощью & v [0]. Очевидно, что если вы сделаете все, что может перераспределить данные, тогда ваши указатели, вероятно, будут признаны недействительными.

Ответ 3

Yep, вы можете использовать его как массив в OpenGL:) Пример:

glBufferData( GL_ARRAY_BUFFER_ARB, dataVec.size() * sizeof( dataVec[0] ), &dataVec[0], GL_STATIC_DRAW_ARB );

Где dataVec std::Vector

Ответ 4

Это даже безопаснее, чем наличие массива в стеке: насколько велик ваш стек? насколько велика ваша матрица (фиксированный размер, но размер может быть увеличен в более поздних версиях)?

Ответ 5

Если вам действительно нужен std:: array, вы можете использовать boost:: array. Это похоже на общий массив, но поддерживает итераторы, и вы можете легко использовать его с алгоритмами STL.

Ответ 6

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