В C векторная функция push_back увеличит размер пустого массива?

#c #vector #push-back

#c #вектор #push-back

Вопрос:

Быстрый вопрос. Допустим, я объявляю вектор размером 20. И затем я хочу добавить к нему несколько целых чисел, используя push_back.

 vector<int> myVector(20);
myVector.push_back(5);
myVector.push_back(14);
  

Является ли емкость моего вектора теперь 22 или все еще 20? Были ли добавлены 5 и 14 к индексам [19] и [20] соответственно? Или они находятся в [0] и [1]?

Ответ №1:

После этих утверждений его емкость определяется реализацией. (Пожалуйста, обратите внимание, что это отличается от его размера.)


 vector<int> myVector(20);
  

Это создает вектор, заполненный двадцатью 0. Его размер равен ровно двадцати, а емкость — не менее двадцати. Независимо от того, точно ли это двадцать, определяется реализацией; может быть больше (на практике, вероятно, нет).

 myVector.push_back(5);
  

После этого двадцать первый элемент массива равен 5, а емкость снова определяется реализацией. (Если раньше емкость была ровно двадцать, теперь она увеличивается неопределенным образом.)

 myVector.push_back(14);
  

Аналогично, теперь двадцать второй элемент массива равен 14, а емкость определяется реализацией.


Если вы хотите зарезервировать место, но не вставлять элементы, вы должны сделать это следующим образом:

 vector<int> myVector;
myVector.reserve(20); // capacity is at least twenty, guaranteed not
                      // to reallocate until after twenty elements are pushed

myVector.push_back(5); // at index zero, capacity at least twenty.
myVector.push_back(14); // at index one, capacity at least twenty.
  

Комментарии:

1. Обратите внимание, что стандарт C 03 23.2.4 / 1 требует, чтобы vector s «поддерживал (амортизировал) операции вставки и стирания с постоянным временем в конце», поэтому на практике емкость обычно увеличивается в два раза, когда push_back() требуется больше места.

2. Хорошо. Спасибо. Я не знал, что он будет заполнен 20 0. Это действительно испортило бы мою программу. Я не знаю, почему я не подумал просто не указывать размер, учитывая, насколько они динамичны, и это то, что мне нужно. Сумасшедший от моего имени.

Ответ №2:

  • size это количество элементов в векторном контейнере.
  • capacity это размер выделенного пространства для хранения
  • push_back эффективно увеличивает размер вектора на единицу, что вызывает перераспределение внутренней выделенной памяти, если размер вектора был равен емкости вектора до вызова.

Дополнительная информация: http://www.cplusplus.com/reference/stl/vector /

Ответ №3:

push_back увеличивает размер std::vector и помещает новые элементы в конец vector (у других контейнеров также есть push_front способ сделать то же самое спереди).

Однако существует разница между размером и емкостью a vector . Размер относится к тому, сколько элементов на самом деле находится в vector данный момент; емкость относится к общему количеству элементов, которые vector могут храниться без перераспределения памяти. Это возможно для reserve() памяти, если вы знаете, что собираетесь добавить несколько элементов, и не хотите увеличивать размер по vector частям.

Комментарии:

1. Итак, push_back не увеличивает емкость, верно? Если только этот вектор уже не работает на полную мощность.

2. Правильно, это не обязательно увеличивает емкость. Я упоминаю об этом только потому std::vector , что возникает проблема с проведением различия, поэтому важно правильно использовать термины, особенно при чтении документации для std::vector .

Ответ №4:

Поскольку вектор не является пустым, но имеет размер 20 (содержит 20 элементов), а у вас push 2 элемента back , теперь он содержит 22 элемента. Но новые элементы размещаются не с индексами 19 и 20, а с 20 и 21.

Если вы действительно хотите зарезервировать достаточно памяти только для того, чтобы вектор мог содержать 20 элементов (фактически не содержащих каких-либо элементов), чтобы предотвратить дорогостоящие перераспределения, тогда вам следует вызвать

 std::vector<int> myVector;
myVector.reserve(20);
  

В этом случае вектор все еще пуст, но у него достаточно памяти, чтобы добавить по крайней мере 20 элементов ( push_back например, используя) без необходимости перераспределять его внутреннюю память. В этом случае вектор содержит только 2 элемента, которые вы push _back отредактировали.

Комментарии:

1. Очень полезно, спасибо. По сути, я хочу создать вектор и добавлять элементы только в конец. Мне не приходило в голову, что мне даже не нужно указывать размер изначально, потому что векторы являются динамическими. Спасибо!

Ответ №5:

push_back увеличит емкость вектора, по крайней мере, до нового размера вектора, но, возможно (т. Е. Вероятно), несколько больше.

Поскольку push_back требуется для выполнения за O (1) амортизированное время, каждое перераспределение будет кратным старой емкости. В типичной реализации это кратное равно 2.

Но точное увеличение емкости не указано. Если вам требуется точный контроль над емкостью, используйте reserve .

Перечитывая ваш вопрос, я не уверен, что вы понимаете разницу между размером вектора и его емкостью. Размер — это количество элементов. Емкость — это количество элементов, которые может содержать вектор без выполнения перераспределения. То есть вы можете push_back использовать элементы capacity()-size() до того, как произойдет перераспределение.

В вашем примере 5 и 14 появятся в MyVector[20] и MyVector[21] соответственно.

Комментарии:

1. Правильно. Чего я не понял, так это того, что векторы не требуют емкости при их создании, то есть они точечные — они динамические, верно? Так что бессмысленно давать им начальную емкость.

2. @iaacp: Нет, это не бессмысленно. Если вы заранее знаете, сколько материала вы планируете поместить внутрь вектора, но у вас нет фактического материала под рукой при инициализации вектора, тогда вы можете reserve() указать количество, чтобы vector не нужно было выполнять какое-либо перераспределение.

3. @iiacp: это не бессмысленно, если вы действительно заботитесь о перераспределении. Перераспределение (а) требует времени и (б) делает недействительными ссылки / указатели на элементы внутри вектора. reserve позволяет установить емкость, чтобы избежать будущих перераспределений. Обратите внимание, что в вашем примере задается размер вектора, а не емкость . Вы создаете вектор из 20 неинициализированных целых чисел.

Ответ №6:

Ну, vector имеет функцию-член push_back . Другие последовательности, подобные deque have push_front .

0, 1, 2, ……, окончательный

после добавления:

0, 1, 2, ….., финал, дополнение, …

Вы можете вспомнить, что:

 capacity() returns the number of elements in the vector sufficient,
without allocating additional memory.
This number can be greater or equal to size.
  

То есть вы не можете добавлять спереди или посередине, поскольку vector специализирован для быстрого доступа к элементам по индексу. Если вы хотите добавить спереди и сзади, вы можете использовать deque , который похож на vector . Если вы хотите добавить спереди, сзади и везде, где вы можете использовать list . Обратите внимание, что list это не обеспечивает индексацию типа deque и vector .

Однако предполагается, что вектор имеет большую емкость, чем его фактический размер. Когда вы добавляете в него элементы, нет необходимости выделять дополнительную память. Это происходит, только если емкость равна размеру. На многих компиляторах новая емкость будет вдвое больше старой. После выделения он копирует все элементы в новое местоположение. Однако такое поведение может быть дорогостоящим с точки зрения памяти.