Подтвердить что ты не робот

Где std::vector выделяет свою память?

Рассмотрим следующий фрагмент кода:

#include <vector>
using namespace std;

void sub(vector<int>& vec) {
    vec.push_back(5);
}

int main() {
    vector<int> vec(4,0);
    sub(vec);
    return 0;
}

Предполагая, что "vec" не осталось места для хранения 5 в "под" функции, где она выделяет новую память?

В кадре стека подфункции? В этом случае 5 будет удалено в конце вспомогательной функции. Но кадр стека основной функции не может расти, так как в этот момент стек стека подфункции лежит поверх стека.
Разделяет ли std::vector память для своих элементов в куче? Но как он освобождает память кучи? Если это локальный вектор в стеке, кадр стека функции, включая вектор, удаляется в конце, не сигнализируя, что вектор будет удален?

4b9b3361

Ответ 1

Предоставляет ли std::vector память для своих элементов в куче?

Да. Или, точнее, он выделяет на основе распределителя, который вы проходите при строительстве. Вы не указали один, поэтому вы получаете распределитель по умолчанию. По умолчанию это будет куча.

Но как он освобождает память кучи?

Через его destructor, когда он выходит за рамки. (Обратите внимание, что указатель на вектор, выходящий из области действия, не вызовет деструктор). Но если вы передали значение sub, вы построили (и позже уничтожили) новую копию. 5 затем будет отброшен назад на эту копию, копия будет очищена, а вектор в main останется нетронутым.

Ответ 2

Все контейнеры в STL параметризуются аргументами шаблона, обычно последний аргумент называется A или Allocator и по умолчанию имеет значение std::allocator<...>, где ... представляет тип значения, хранящегося в контейнере.

Allocator - это класс, который используется для обеспечения памяти и сборки/уничтожения элементов в этой области памяти. Он может выделять память из пула или непосредственно из кучи, в зависимости от того, из какого вы построили распределитель. По умолчанию std::allocator<T> представляет собой простую оболочку вокруг ::operator new и, таким образом, выделяет память в куче, как вы предполагали.

Память распределяется по требованию и освобождается по меньшей мере, когда вызывается деструктор vector. С++ 11 вводит shrink_to_fit для освобождения памяти раньше. Наконец, когда вектор перерастает его текущую емкость, выполняется новое (большее) выделение, объекты перемещаются на него, и старое выделение освобождается.

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

Ответ 3

Также обратите внимание, что ваш вектор (vec) - это сам объект. Он находится в стеке, и когда этот объект выходит за пределы области действия (это конец main в вашем случае), он разрушается. Память для элементов выделяется при инициализации этого объекта и выпущена с его уничтожением, что является прекрасным примером RAII идиомы, поскольку управление ресурсами элементов привязан к продолжительности жизни векторного объекта.

Ответ 4

Потому что вы указали sub адрес вектора в куче, он будет выделяться в куче. Если нет места, исключение должно быть выбрано.