Гарантируется ли непрерывность элементов std:: vector?


мой вопрос прост: гарантируются ли элементы std:: vector смежными? В order word, могу ли я использовать указатель на первый элемент std::vector в качестве c-массива?

Если мне не изменяет память, стандарт 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'
    }
}
7 86

7 ответов:

Это было пропущено из стандарта C++98, но позже добавлено как часть TR. Предстоящий стандарт C++0x, конечно же, будет содержать это в качестве требования.

из n2798 (черновик C++0x):

23.2.6 шаблон класса вектор [вектор]

1 вектор-это контейнер последовательности, которая поддерживает итераторы произвольного доступа. Кроме того, он поддерживает (амортизируется) постоянное время вставки и стирания в конце; вставка и удаление данных середина занимает линейное время. Место хранения управление осуществляется автоматически, хотя могут быть даны подсказки для повышения эффективности. Элементы вектор хранятся последовательно, что означает, что если v-вектор, где T-некоторый тип другой чем bool, то он подчиняется тождеству &v[n] = = &v[0] + n для всех 0

как указывали другие ответы, содержимое вектора гарантированно будет непрерывным (за исключением странности була).

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

стандарт действительно гарантирует, что a vector непрерывно в памяти и что &a[0] можно передать в C функция, которая ожидает массив.

исключение из этого правила составляет vector<bool>, который использует только один бит для каждого bool таким образом, хотя и имеет непрерывную память не может быть использован в качестве bool* (это широко считается ложной оптимизацией и ошибкой).

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

как уже говорили другие,vector внутренне использует непрерывный массив объектов. Указатели в этот массив должны рассматриваться как недопустимые всякий раз, когда любая неконстантная функция-член вызывается IIRC.

однако, есть исключение!!

vector<bool> имеет специализированную реализацию, предназначенную для экономии места, так что каждый bool использует только один бит. Базовый массив не является непрерывным массивом арифметики bool и массива на vector<bool> не работает vector<T> бы.

(Я полагаю, что это также возможно, что это может быть верно для любой специализации вектора, так как мы всегда можем реализовать новый. Однако,std::vector<bool> это единственная, err, стандартная специализация, при которой простая арифметика указателя не будет работать.)

Я нашел этот поток, потому что у меня есть случай использования, когда векторы, использующие непрерывную память, являются преимуществом.

Я учусь использовать объекты буфера вершин в OpenGL. Я создал класс-оболочку, чтобы содержать логику буфера, поэтому все, что мне нужно сделать, это передать массив поплавков и несколько значений конфигурации для создания буфера. Я хочу иметь возможность генерировать буфер из функции на основе пользовательского ввода, поэтому длина не известна во время компиляции. Что-то подобное будет самое простое решение:

void generate(std::vector<float> v)
{
  float f = generate_next_float();
  v.push_back(f);
}

теперь я могу передать поплавки вектора в виде массива для функций, связанных с буфером OpenGL. Это также устраняет необходимость в sizeof для определения длины массива.

Это намного лучше, чем выделять огромный массив для хранения поплавков и надеяться, что я сделал его достаточно большим или сделал свой собственный динамический массив с непрерывным хранилищем.

да, элементы вектора std:: гарантированно будут смежными.

cplusplus.com:

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