Мой вопрос прост: гарантированно ли элементы std :: vector смежны? В порядке слов, могу ли я использовать указатель на первый элемент 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'
}
}
values
внутри этогоif
блока. Однако я не знаю ответа на ваш вопрос, поэтому просто оставляю комментарий. :)values
, которые изменяют, в частности, которые изменяют его размер (например,push_back()
), могут вызвать перераспределение базового вектора, что делает недействительным указатель, скопированный вarray
. Тот же принцип лежит в основе использования vector :: iterator вместо указателя на вектор. :)Ответы:
Это было пропущено в стандарте C ++ 98, но позже было добавлено как часть TR. Грядущий стандарт C ++ 0x, конечно, будет содержать это как требование.
Из n2798 (черновик C ++ 0x):
источник
std::vector
являются смежными. Например .: вstd::vector<std::vector<int>> v
элементахv[0]
,v[1]
... сохраняются впоследствии в памяти, но элементv[0].back()
иv[1].front()
не гарантируется.Как указывали другие ответы, содержимое вектора гарантированно будет непрерывным (за исключением странности bool).
Комментарий, который я хотел добавить, заключается в том, что если вы выполняете вставку или удаление вектора, что может привести к перераспределению памяти вектором, вы сделаете все ваши сохраненные указатели и итераторы недействительными.
источник
Стандарт действительно гарантирует, что a
vector
является непрерывным в памяти и&a[0]
может быть переданоC
функции, которая ожидает массив.Исключением из этого правила является
vector<bool>
использование только одного бита на каждый,bool
поэтому, хотя у него есть непрерывная память, его нельзя использовать в качествеbool*
(это широко считается ложной оптимизацией и ошибкой).Кстати, почему бы вам не использовать итераторы? Вот для чего они нужны.
источник
Как уже говорили другие,
vector
внутренне использует непрерывный массив объектов. Указатели на этот массив должны рассматриваться как недопустимые, если какая-либо неконстантная функция-член вызывается IIRC.Однако есть исключение !!
vector<bool>
имеет специальную реализацию, предназначенную для экономии места, так что каждый логический объект использует только один бит. Базовый массив не является непрерывным массивом bool, и арифметика массиваvector<bool>
работает не так, как еслиvector<T>
бы.(Я полагаю, также возможно, что это может быть верно для любой специализации вектора, поскольку мы всегда можем реализовать новую. Однако
std::vector<bool>
это единственная, ошибочная, стандартная специализация, при которой простая арифметика указателей не работает.)источник
std::vector
, и все другие векторы должны использовать непрерывное хранилище. Следовательно,std::vector<bool>
это (к счастью) единственный странный стандартный вектор. (Я твердо придерживаюсь мнения, что эту специализацию следует исключить и заменить, например, astd::dynamic_bitset
с почти такой же функциональностью. Это неплохая структура данных, это просто не вектор.)Я нашел этот поток, потому что у меня есть вариант использования, когда векторы, использующие непрерывную память, являются преимуществом.
Я учусь использовать объекты буфера вершин в OpenGL. Я создал класс-оболочку, содержащий логику буфера, поэтому все, что мне нужно сделать, это передать массив с плавающей запятой и несколько значений конфигурации для создания буфера. Я хочу иметь возможность сгенерировать буфер из функции на основе пользовательского ввода, поэтому длина не известна во время компиляции. Самым простым решением было бы сделать что-то подобное:
Теперь я могу передать векторные числа с плавающей запятой в виде массива в функции, связанные с буфером OpenGL. Это также устраняет необходимость в sizeof для определения длины массива.
Это намного лучше, чем выделить огромный массив для хранения чисел с плавающей запятой и надеяться, что я сделал его достаточно большим, или создать свой собственный динамический массив с непрерывным хранилищем.
источник
v
а не наv
себя? потому чтоv
только передача вызовет создание копии внутри функции, которая перестанет существовать после завершения функции. Таким образом, вы нажимаете что-то на вектор только для того, чтобы удалить вектор, когда функция завершится.cplusplus.com:
источник
Да, элементы std :: vector гарантированно будут смежными.
источник