Можно ли использовать std::vector capacity/size/reserve для ручного управления выделением векторной памяти?

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

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

код

std::vector<unsigned int> data;
while (condition) {
    // Reallocate here
    // get_elements_required() gives an estimate that is guaranteed to be >= the actual nmber of elements.
    unsigned int estimated_elements_required = get_elements_required(...);
    if ((data.capacity() - data.size()) <= estimated_elements_required) {
        data.reserve(min(data.capacity() * 2, data.max_length - 1));
    }

    ...

    // NEVER reallocate here, I would rather see the program crash actually...
    for (unsigned int i = 0; i < get_elements_to_add(data); ++i) {
        data.push_back(elements[i]);
    }
}

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


person user3235200    schedule 26.04.2014    source источник
comment
Вероятно, вы захотите использовать resize(() вместо reserve().   -  person πάντα ῥεῖ    schedule 26.04.2014
comment
И вы не просто вызываете data.reserve(elements_required);, потому что.... ? Или вы имели в виду, что elements_required на самом деле является elements_to_add (источник которого в этом коде является загадкой)?   -  person WhozCraig    schedule 26.04.2014
comment
@πάνταῥεῖ: Он увеличивает размер ниже, когда добавляет элементы.   -  person Benjamin Bannier    schedule 26.04.2014
comment
Да, вы можете использовать reserve осторожно, чтобы точно контролировать выделение памяти. Он гарантированно не будет выделен, если вы не добавите больше текущего capacity.   -  person M.M    schedule 26.04.2014
comment
как elements_to_add связано с elements_required, data.size() и data.capacity()*2 в вашем коде?   -  person MikeMB    schedule 26.04.2014


Ответы (1)


Да, это сработает.

Из определения reserve:

Гарантируется, что во время вставок, которые происходят после вызова reserve(), не происходит никакого перераспределения до тех пор, пока вставка не сделает размер вектора больше, чем значение capacity().

person Mankarse    schedule 26.04.2014
comment
Это часть iff, о которой я беспокоюсь. Возможность для некоторых эвристик, которые предполагают массовое добавление и перераспределение, когда размер › 90% емкости или что-то в этом роде. - person user3235200; 26.04.2014
comment
@user3235200: user3235200: Это было бы незаконно, потому что они нарушили бы семантику аннулирования указателя/ссылки пользователя. - person Puppy; 26.04.2014
comment
@DeadMG: Альтернативная интерпретация заключается в том, что вы должны проверять capacity() после каждого вызова push_back, и если он не изменился, вы знаете, что перераспределения не произошло. - person Mankarse; 26.04.2014
comment
Я бы предположил, что if в этой цитате означает if and only if. - person M.M; 26.04.2014
comment
@MattMcNabb: я имел в виду if and only if, когда писал iff, но не когда писал if, просто чтобы уточнить. - person user3235200; 26.04.2014
comment
Я имел в виду пост Манкарсе - person M.M; 26.04.2014
comment
В общем, стандарт различает «если» и «если» и «только если». Однако для std::vector::reserve() стандарт гарантирует, что ... no reallocation takes place during insertions that happen after a call to reserve() until the time when an insertion would make the size of the vector greater than the value of capacity() - person MikeMB; 26.04.2014
comment
@MikeMB: Спасибо за это. Отредактировано. - person Mankarse; 26.04.2014