Сбой программы при использовании vector :: emplace [duplicate]

Использование удивительной библиотеки Pillow :

  & gt; & gt; & gt; & gt;  из импорта PIL Изображение & gt; & gt; & gt; & gt;  img = Image.open ('test.png') & gt; & gt; & gt; & gt; & gt;  img.show ()  

Это откроет изображение в вашем средстве просмотра изображений по умолчанию.

120
задан iammilind 13 September 2011 в 09:36
поделиться

4 ответа

Две функции делают разные вещи!

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

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

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

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

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

204
ответ дан Community 15 August 2018 в 20:45
поделиться
  • 1
    Я отредактировал вопрос. У меня есть определенная оценка для vector. – iammilind 13 September 2011 в 09:37
  • 2
    «Единственный случай, когда имеет смысл reserve (), заключается в том, что у вас есть достаточно точная оценка общего размера, который вам нужно будет легко получить заранее. & quot; - не строго верно, так как вызов reserve() самостоятельно в определенное время иногда может помочь вам управлять любыми указателями или итераторами, которые у вас есть для элементов вектора (и, в частности, они недействительны путем перераспределения). Не то, чтобы в этом вопросе есть какие-то признаки того, что такие вещи продолжаются. И это правда, что вам нужно знать верхнюю границу того, сколько элементов вы добавите за время, когда нужны ваши указатели / итераторы. – Steve Jessop 13 September 2011 в 10:20
  • 3
    @Jan: Ну, это хрупко или не соответствует тому, насколько сложно вы сделали это для себя, чтобы сохранить требуемое свойство. Что-то вроде x.reserve(x.size() + newdata); vector<int>::iterator special_element = get_special_element(x); for (int i = 0; i < newdata; ++i) { if some_function(i, special_element) x.push_back(i); } довольно устойчиво, поскольку резервирование пространства касается. Я не знаю, сколько элементов будет добавлено, но у меня есть верхняя граница. Конечно, если у вас есть сомнения, с векторами вы можете просто использовать индексы вместо итераторов, разница обычно незначительна. – Steve Jessop 13 September 2011 в 10:33
  • 4
    Ваша формулировка имеет смысл для кого-то, кто уже знает правильный ответ, но может легко ввести в заблуждение людей, которые должны задать вопрос. & quot; resize () ... будет вставлять заданное количество элементов в вектор " - только в первый раз, когда он используется - он обычно вставляет разницу между запрошенным номером и ранее существовавшим size(). «Метод reserve () только распределяет память» - он может или не может выделять память в зависимости от того, достаточно ли capacity(), может также потребоваться перемещение элементов и освобождение их исходной памяти. «хотят избежать пары распределений», и т.д. – Tony Delroy 28 December 2011 в 10:46
  • 5
    Фактически, резервирование перед нажатием является жизненно важным и должно использоваться. Предположим, что вы кодируете какой-то трехмерный модельный загрузчик, а модель имеет 15000 вершин. Если вы попробуете push_back каждую вершину во время загрузки без предварительного выделения их в первую очередь, это займет много времени. Я лично испытал это, я попытался загрузить автомобиль .obj модель с почти 100 000 вершин, потребовалось 30 секунд. Затем я реорганизовал код, используя предварительное выделение с помощью .reserve (), теперь это занимает 3 секунды. Просто положив .reserve (100000) в начале кода, сохраненный 27 секунд. – deniz 12 October 2013 в 08:25

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

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

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

1
ответ дан dip 15 August 2018 в 20:45
поделиться

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

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

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

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

2
ответ дан justin 15 August 2018 в 20:45
поделиться

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() к нему, но он не будет выделять новую память еще раз, пока не закончится пространство, которое вы зарезервировали для него.

23
ответ дан phonetagger 15 August 2018 в 20:45
поделиться
  • 1
    После выполнения reserve(N) мы можем использовать operator [] безвредно. верный ? – iammilind 13 September 2011 в 09:48
  • 2
    Хотя в большинстве реализаций будет выделяться точная сумма, которую вы запрашиваете с помощью reserve, спецификация требует, чтобы она распределяла по крайней мере так много, поэтому некоторые реализации могут округляться до некоторой границы и, следовательно, показывать более высокую емкость, чем 1000. – Jan Hudec 13 September 2011 в 09:49
  • 3
    @iammilind: Нет, если индекс больше или равен v.size(). Обратите внимание, что reserve(N) не изменяет size() вектора. – Nawaz 13 September 2011 в 09:51
  • 4
Другие вопросы по тегам:

Похожие вопросы: