Почему размер вектора() и емкость () отличаются после push back()
Я только начинаю изучать векторы и немного путаюсь в size() и capacity()
Я мало знаю о них обоих. Но почему в этой программе оба они разные? даже array(10) освобождает место для 10 элементов и инициализирует с 0.
Перед добавлением array.push_back(5)
Так что array.size(); - это 10, это нормально.
Так что array.capacity(); - это 10, это нормально.
После добавления array.push_back(5)
Так что array.size(); - это 11, что нормально (already 10 time 0 is added and then push_back add one more element 5 ).
Итак, array.capacity(); - это 15 Почему? ( is it reserving 5 blocks for one int? ).
#include <iostream>
#include <vector>
int main(){
std::vector<int> array(10); // make room for 10 elements and initialize with 0
array.reserve(10); // make room for 10 elements
array.push_back(5);
std::cout << array.size() << std::endl;
std::cout << array.capacity() << std::endl;
return 0;
}
6 ответов:
Стандарт предписывает, что
std::vector<T>::push_back()имеет амортизированнуюO(1)сложность. Это означает, что расширение должно быть геометрическим, скажем, удвоение объема хранилища каждый раз, когда оно заполняется.Простой пример: последовательно
push_back32ints в astd::vector<int>. Вы будете хранить их все один раз, а также делать 31 копию, если вы удваиваете емкость каждый раз, когда она заканчивается. Почему 31? Перед хранением 2-ой элемент, скопировать 1-й; перед хранением 3-й, копировании элементов 1-2, перед хранением 5-й, вы копируете 1-4 и т. д. Так что вы копируете 1 + 2 + 4 + 8 + 16 = 31 раз, с 32 магазинами.Выполнение формального анализа показывает, что вы получаете
Из-за этой стратегии расширения, у вас будетO(N)хранилища и копии дляNэлементов. Это означает амортизированнуюO(1)сложность в расчетеpush_back(часто только магазин без копии, иногда магазин и последовательность копий).size() < capacity()большую часть времени. Lookupshrink_to_fitиreserve, чтобы узнать, как управлять способностью вектора в более мелкозернистая манера.Примечание : с геометрической скоростью роста подойдет любой фактор больше 1, и были некоторые исследования, утверждающие, что 1.5 дает лучшую производительность из-за меньшего количества потраченной памяти (потому что в какой-то момент перераспределенная память может перезаписать старую память).
Это для эффективности, чтобы не нужно было расширять базовую структуру данных каждый раз, когда вы добавляете элемент. то есть не надо звонить
delete/newкаждый раз.
Std::vector::capacity - это не его фактический размер (который возвращается
Другими словами, это размер, которого он может достичь, прежде чем потребуется еще одно перераспределение.size()), а размер фактического внутреннего выделенного размера.Он не увеличивается на 1 каждый раз, когда вы делаете
push_back, Чтобы не вызывать новое перераспределение (что является тяжелым вызовом) для каждого вставленного элемента. Он резервирует больше, потому что не знает, не сделаете ли вы что-нибудь другоеpush_backсразу после этого, и в этом в этом случае ему не придется изменять размер выделенной памяти для следующих 4 элементов.Здесь 4 следующих элемента-это компромисс между 1, который оптимизирует выделение памяти по максимуму, но рискует вскоре снова перераспределить ее, и огромным числом, которое позволит вам быстро сделать много
push_back, но, возможно, зарезервировать много памяти впустую.Примечание : Если вы хотите указать емкость самостоятельно (например, если вы знаете максимальный размер вектора), вы можете сделать это с помощью резервная функция-член.
Используя
Вы фактически заполнили все десять пробелов нулями. Добавление дополнительного элемента ad приведет к расширению емкости благодаря эффективности. В вашем случае бесполезно вызывать функцию reserve, так как вы создали одинаковое количество элементов.std::vector<int> array(10); // make room for 10 elements and initialize with 0
Size()возвращает, сколько значений у вас есть в векторе.И
capacity()возвращает размер выделенной емкости памяти, то есть сколько значений она может содержать в данный момент.
Я думаю, что следующий вопрос может дать вам более подробную информацию о способности вектора.
Я буду ссылаться на ответ в вышеприведенном вопросе.Стратегия роста
capacityнеобходима для удовлетворения амортизированного постоянного временного требования для операцииpush_back. Затем стратегия предназначена для экспоненциального роста, как правило, когда пространства не хватает. Короче говоря,sizeвектора указывают число элементов теперь, в то время какcaptacityпокажите свою способность использоватьpush_backв будущем.
Comments