Выбор между vector:: resize() и vector:: reserve()

Я предварительно выделяю некоторую память моей переменной-члену vector. Ниже кода минимальная часть

class A {
  vector<string> t_Names;
public:
  A () : t_Names(1000) {}
};

Теперь в некоторый момент времени, если t_Names.size() равно 1000. Я намерен увеличить размер на 100. Затем, если он достигнет 1100, снова увеличьте на 100 и т.д.

Мой вопрос в том, что выбрать между vector::resize() и vector::reserve(). Есть ли лучший выбор в этом сценарии?

Изменить. У меня есть точная оценка для t_Names. Я полагаю, что он будет 700 до 800. Однако в определенных (редко) ситуациях он может вырасти больше, чем 1000.

Ответ 1

Две функции выполняют совершенно разные вещи!

Метод resize() (и передающий аргумент конструктору эквивалентен этому) будет вставлять или удалять соответствующее количество элементов в вектор, чтобы сделать его заданным размером ( он имеет необязательный второй аргумент, чтобы указать их значение). Это повлияет на size(), итерация перейдет по всем этим элементам, push_back вставляет после них, и вы можете напрямую обращаться к ним с помощью operator[].

Метод reserve() выделяет только память, но оставляет его неинициализированным. Это влияет только на capacity(), но size() не изменится. Для объектов нет значения, потому что ничего не добавляется к вектору. Если вы вставляете элементы, перераспределение не произойдет, потому что это было сделано заранее, но это единственный эффект.

Так что это зависит от того, что вы хотите. Если вам нужен массив из 1000 элементов по умолчанию, используйте resize(). Если вам нужен массив, к которому вы хотите вставить 1000 элементов, и хотите избежать нескольких распределений, используйте reserve().

EDIT: Комментарий Blastfurnace заставил меня снова прочитать вопрос и понять, что в вашем случае правильный ответ не предопределяет вручную. Просто продолжайте вставлять элементы в конце по мере необходимости. Вектор будет автоматически перераспределяться по мере необходимости и будет делать это более эффективно, чем упомянутый ручной способ. Единственный случай, когда reserve() имеет смысл, - это когда вы имеете достаточно точную оценку общего размера, который вам нужно будет легко получить заранее.

EDIT2: Редактирование рекламного вопроса: если у вас есть начальная оценка, то reserve(), которые оцениваются. Если этого оказалось недостаточно, просто дайте вектору сделать это.

Ответ 2

resize() не только выделяет память, но также создает столько экземпляров, сколько желаемого размера, который вы передаете в resize() в качестве аргумента. Но reserve() выделяет только память, не создает экземпляры. То есть

std::vector<int> v1;
v1.resize(1000); //allocation + instance creation
cout <<(v1.size() == 1000)<< endl;   //prints 1
cout <<(v1.capacity()==1000)<< endl; //prints 1

std::vector<int> v2;
v2.reserve(1000); //only allocation
cout <<(v2.size() == 1000)<< endl;   //prints 0
cout <<(v2.capacity()==1000)<< endl; //prints 1

Выход (онлайн-демонстрация):

1
1
0
1

Так что resize() может быть нежелательно, если вы не хотите создавать созданные по умолчанию объекты. Это тоже будет медленным. Кроме того, если вы push_back() новые элементы к нему, size() вектора будет еще больше увеличиваться за счет выделения новой памяти (что также означает перемещение существующих элементов в вновь выделенное пространство памяти). Если вы использовали reserve() в начале, чтобы обеспечить достаточную выделенную память, size() вектора будет увеличиваться, если вы push_back() к нему, , но он не будет выделять новую память еще до ее запуска из пространства, которое вы зарезервировали для него.

Ответ 3

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

Есть ли лучший выбор в этом сценарии?

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

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

Ответ 4

Из вашего описания, похоже, вы хотите "зарезервировать" выделенное пространство хранения векторных t_Names.

Обратите внимание, что resize инициализирует вновь выделенный вектор, где reserve просто выделяет, но не создает. Следовательно, "резерв" намного быстрее, чем "изменить размер"

Вы можете сослаться на документацию о различии resize и reserve