Изменение резервной памяти вектора C ++ - PullRequest
5 голосов
/ 26 ноября 2008

У меня есть вектор с 1000 "узлами"

 if(count + 1 > m_listItems.capacity())
     m_listItems.reserve(count + 100);

Проблема в том, что я также очищаю ее, когда собираюсь пополнить.

m_listItems.clear();

Емкость не меняется. Я использовал изменение размера (1); но это, кажется, не меняет способности. Так как же изменить резерв?

Ответы [ 5 ]

20 голосов
/ 26 ноября 2008
vector<Item>(m_listItems).swap(m_listItems);

снова сократится m_listItems: http://www.gotw.ca/gotw/054.htm (Херб Саттер)

Если вы все равно хотите очистить его, поменяйте местами с пустым вектором:

vector<Item>().swap(m_listItems);

что, конечно, намного эффективнее. (Обратите внимание, что смена векторов в основном означает просто замену двух указателей. Ничего особенного не происходит)

2 голосов
/ 26 ноября 2008

Вы можете поменять вектор, как предлагали другие, и как описано в http://www.gotw.ca/gotw/054.htm, но имейте в виду, что он не свободен, вы выполняете копию каждого элемента, потому что Vector должен выделить новый, меньший кусок памяти и скопировать все старое содержимое. (Операция подкачки по существу бесплатна, но вы меняете местами временную инициализацию с копией исходных векторных данных, которая не свободна)

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

std::vector<foo> v(1000); // Create a vector with capacity for 1000 elements

А если вы заранее не знаете емкость, то почему это имеет значение, не расходует ли она немного места? Стоит ли тратить время на копирование каждого элемента в новый и меньший вектор (что будет делать std :: vector (v) .swap (v)), просто чтобы сэкономить несколько килобайт памяти?

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

Редактировать

baash05: что если бы у вас было 1000000 предметов 10 мегабайт оперативной памяти. Вы бы сказали уменьшение суммы накладных расходов важно?

Нет. Изменение размера вектора требует больше памяти, временно, поэтому, если у вас ограниченная память, это может сломать ваше приложение. (Вам необходимо иметь исходный вектор в памяти, и временный, прежде чем вы сможете поменять их, так что в итоге вы будете использовать в два раза больше ОЗУ в этой точке). После этого вы можете сэкономить небольшой объем памяти (до пары МБ), но это не имеет значения, потому что избыточная емкость в векторе никогда не будет доступна, поэтому она будет помещена в файл подкачки, и поэтому нет в первую очередь рассчитывайте на ограничение вашей ОЗУ.

Если у вас есть 1000000 предметов, то вы должны инициализировать вектор с правильным размером , в первую очередь .

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

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

1 голос
/ 26 ноября 2008

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

1 голос
/ 26 ноября 2008

Вы можете swap это с новым вектором, который имеет желаемую емкость.

vector< int > tmp;
old.swap( tmp );
1 голос
/ 26 ноября 2008

Вы можете попробовать эту технику из здесь

std::vector< int > v;
// ... fill v with stuff...
std::vector< int >().swap( v );
...