Элементы std::vector гарантируют непрерывность?
Мой вопрос прост: std::vector элементы гарантированно смежны? В качестве слова, могу ли я использовать указатель на первый элемент std::vector как C-массив?
Если моя память мне хорошо помогает, стандарт С++ не дает такой гарантии. Однако требования std::vector были такими, что их было практически невозможно встретить, если элементы не были смежными.
Может ли кто-нибудь прояснить это?
Пример:
std::vector<int> values;
// ... fill up values
if( !values.empty() )
{
int *array = &values[0];
for( int i = 0; i < values.size(); ++i )
{
int v = array[i];
// do something with 'v'
}
}
Ответы
Ответ 1
Это было пропущено из стандартного С++ 98, но позже добавлено как часть TR. Предстоящий стандарт С++ 0x, конечно, будет содержать это как требование.
Из n2798 (черновик С++ 0x):
23.2.6 Вектор шаблона шаблона [вектор]
1 Вектор представляет собой контейнер последовательности, который поддерживает итераторы с произвольным доступом. Кроме того, он поддерживает (амортизирует) постоянное время вставки и стирания операций в конце; вставлять и стирать в середине, принимать линейное время. Место хранения управление обрабатывается автоматически, хотя можно дать подсказки для повышения эффективности. Элементы вектор сохраняются смежно, что означает, что если v - вектор, где T - некоторый тип другого чем bool, тогда он подчиняется идентификатору & v [n] == & v [0] + n для всех 0 <= n < V.SIZE().
Ответ 2
Как указывали другие ответы, содержимое вектора гарантировано будет непрерывным (за исключением странности bool).
Комментарий, который я хотел добавить, заключается в том, что если вы вставляете или удаляете вектор, что может привести к перераспределению его памяти, то вы заставите все ваши сохраненные указатели и итераторы быть недействительными.
Ответ 3
Стандарт фактически гарантирует, что a vector
является непрерывным в памяти и что &a[0]
может быть передан функции C
, которая ожидает массив.
Исключением из этого правила является vector<bool>
, который использует только один бит на bool
, поэтому, хотя у него есть непрерывная память, он не может использоваться как bool*
(это широко считается ложной оптимизацией и ошибка).
Кстати, почему бы вам не использовать итераторы? Для чего они предназначены.
Ответ 4
Как уже говорилось, vector
внутренне использует непрерывный массив объектов. Указатели в этот массив должны рассматриваться как недействительные, когда любая неконстантная функция-член называется IIRC.
Однако есть исключение!!
vector<bool>
имеет специализированную реализацию, предназначенную для экономии места, так что каждый bool использует только один бит. Базовый массив не является смежным массивом bool и арифметики массива на vector<bool>
не работает, как vector<T>
.
(я полагаю, также возможно, что это может быть справедливо для любой специализации вектора, поскольку мы всегда можем реализовать новую. Однако std::vector<bool>
- единственная стандартная специализация с ошибкой, на которой простая арифметика указателя не будет работа.)
Ответ 5
Я нашел этот поток, потому что у меня есть прецедент, в котором преимуществом являются векторы, использующие непрерывную память.
Я изучаю, как использовать объекты вершинного буфера в OpenGL. Я создал класс-оболочку, содержащий логику буфера, поэтому мне нужно всего лишь передать массив поплавков и несколько значений конфигурации для создания буфера.
Я хочу иметь возможность генерировать буфер из функции, основанной на пользовательском вводе, поэтому длина не известна во время компиляции. Сделать что-то подобное было бы самым простым решением:
void generate(std::vector<float> v)
{
float f = generate_next_float();
v.push_back(f);
}
Теперь я могу передать векторные float как массив в функции, связанные с буфером OpenGL. Это также устраняет необходимость в sizeof для определения длины массива.
Это намного лучше, чем выделение огромного массива для хранения поплавков и надеясь, что я сделал его достаточно большим или создав собственный динамический массив со смежным хранилищем.
Ответ 6
Да, элементы std::vector гарантируют непрерывность.
Ответ 7
cplusplus.com:
Векторные контейнеры реализуются как динамические массивы; Подобно регулярным массивам, векторные контейнеры имеют свои элементы, хранящиеся в смежных местах хранения, что означает, что их элементы могут быть доступны не только с использованием итераторов, но и с использованием смещений на регулярных указателях на элементы.