С++: безопасно ли работать с 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
Работа в многопоточной среде и распределении динамической памяти может вызвать проблему, потому что вектор, как правило, представляет собой непрерывный кусок памяти и указателей, возможно, нет!