c ++ вставка элементов в конце вектора - PullRequest
1 голос
/ 21 сентября 2011

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

В основном я использую вектор :: резерв для расширения моего вектора _children при необходимости:

if (_children.capacity() == _children.size())
{
     _children.reserve(_children.size() * 2);
}

и использование vector :: at () для вставки нового элемента в конце _children вместо vector :: push_back ():

_children.at(_children.size()) = child;

_children уже содержит один элемент, поэтому первый элемент должен быть вставлен в позицию 1, а емкость в это время равна 2.

Несмотря на это, выдается ошибка out_of_range. Может кто-нибудь объяснить мне, что я здесь не так понял? Разве нельзя просто вставить дополнительный элемент, даже если выбранная позиция меньше емкости вектора? Я могу выложить больше кода, если это необходимо.

Заранее спасибо.

/ * Мадс 1015 *

Ответы [ 7 ]

8 голосов
/ 21 сентября 2011

Увеличение емкости не увеличивает количество элементов в векторе. Это просто гарантирует, что вектор имеет возможность расти до требуемого размера без перераспределения памяти. Т.е. вам все равно нужно позвонить push_back().

Имейте в виду, призыв reserve() увеличить емкость геометрически - пустая трата усилий. std::vector уже делает это.

1 голос
/ 21 сентября 2011

Это не то, для чего at(). at() - это проверенная версия [], то есть доступ к элементу. Но reserve() не меняет количество элементов.

Вы должны просто использовать reserve() с последующим push_back или emplace_back или insert (в конце); все они будут эффективными, поскольку они не приведут к перераспределению, если вы останетесь без ограничения емкости.

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

1 голос
/ 21 сентября 2011

Ни at, ни reserve не увеличивают размер вектора (последний увеличивает емкость , но не размер ).

Кроме того, вашпопытка оптимизации почти наверняка является излишней;Вы должны просто push_back элементы в массиве и полагаться на std::vector, чтобы разумно расширить его возможности.

1 голос
/ 21 сентября 2011

Это вызывает доступ за пределы. Резервирование памяти не влияет на размер вектора.

По сути, вы делаете вручную то, что push_back делает внутри. Как вы думаете, почему это будет эффективнее?

0 голосов
/ 21 сентября 2011

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

В вашем примере _children.size() равен 1, но в позиции 1 элемента нет. Вы можете использовать присваивание только для замены существующих элементов, но не для добавления новых. По определению, последний элемент находится в _children.at(_children.size()-1).

Правильный способ - просто использовать push_back(), который высоко оптимизирован и быстрее, чем вставка в индекс. Если вы заранее знаете, сколько элементов вы хотите добавить, вы, конечно, можете использовать reserve() в качестве оптимизации.

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

См. Также http://www.cplusplus.com/reference/stl/vector/capacity/

0 голосов
/ 21 сентября 2011

vector::reserve является только внутренним резервирующим пространством, но не создает объекты и не изменяет внешний размер вектора.Если вы используете резерв, вам нужно использовать push_back.Кроме того, vector::at выполняет проверку диапазона, что делает его намного медленнее по сравнению с vector::operator[].

Вы пытаетесь имитировать часть вектора поведения, которая уже реализована внутри.Он будет увеличиваться по своим размерам на определенный коэффициент (обычно около 1,5 или 2) каждый раз, когда ему не хватает места.Если вы знаете, что отбрасываете множество объектов и хотите использовать только одно перераспределение:

vec.reserve(vec.size() + nbElementsToAdd);

Если вы не добавляете достаточно элементов, это потенциально хуже, чем поведение по умолчанию vector.

0 голосов
/ 21 сентября 2011

Вы должны различать емкость и размер . Вы можете назначить только в пределах размера, а резерв влияет только на емкость.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...