Гарантируется ли непрерывность элементов 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 ответов:
Это было пропущено из стандарта 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 для определения длины массива.
Это намного лучше, чем выделять огромный массив для хранения поплавков и надеяться, что я сделал его достаточно большим или сделал свой собственный динамический массив с непрерывным хранилищем.
векторные контейнеры реализованы в виде динамических массивов; так же, как и обычные массивы, векторные контейнеры имеют свои элементы, хранящиеся в смежных местах хранения, что означает, что их элементы могут быть доступны не только с помощью итераторов, но и с помощью смещений на обычных указателях на элементы.