Элементы 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:

Векторные контейнеры реализуются как динамические массивы; Подобно регулярным массивам, векторные контейнеры имеют свои элементы, хранящиеся в смежных местах хранения, что означает, что их элементы могут быть доступны не только с использованием итераторов, но и с использованием смещений на регулярных указателях на элементы.