Это скорее теоретический вопрос, чем проблема.

Насколько я понимаю, std :: vector будет динамически изменять размер / перераспределять память при добавлении, удалении или создании.

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

  1. Что мешает следующему примеру перезаписать пространство памяти string1?

  2. Являются ли векторы смежными так же, как массивы?

  3. Если имеется доступная общая память для вектора, но он не является смежным, будет ли он фрагментировать пространство памяти?

#include <vector>

using namespace std;

int main(){
    string string1 = "Some really large string";  

    /* A bunch of other random declarations take place 
    ...
    */

    vector<int> vector1;

    for(int i = 0; i < 10; i++)
    {
       vector1.push_back(i);
    }
}
-2
Cody B 20 Ноя 2019 в 19:47

2 ответа

Лучший ответ

Как эти ответы?

  1. ОС делает (или кто-то другой, кто занимается выделением вашей памяти). Обычно распределители по умолчанию для векторов и строк вызывают ОС для выделения памяти в куче. (очень маленькие строки могут идти в стек с «оптимизацией малых строк, <~ 16 байтовых строк».) ОС гарантирует, что они не конфликтуют.

  2. Да, стандарт гарантирует непрерывную память для вектора.

  3. Нет, он запросит нужный ему размер блока, а ОС (или любой другой распределитель) предоставит его или потерпит неудачу. Defrag - это задача ОС.

РЕДАКТИРОВАТЬ: то, что @parktomatomi говорит, правильно. std::vector<T> выделяет достаточно памяти, скажем, для 8 элементов, для начала, затем для 9-го они будут повторно запрашивать 16 элементов, копировать все заново и освобождать блок из 8 элементов. То же самое с 32 элементами и т. Д. depentdant, но это что-то в этом роде. Вы можете использовать std::vector.reserve(), чтобы избежать процесса перераспределения и копирования. Обычно это того стоит, если у вас есть идеальная информация, в противном случае просто оставить ее алгоритму удвоения обычно хорошо.

std::array<T, N> имеет фиксированный размер и стек выделяется точно так же, как примитивные типы (int, double и т. Д.). Таким образом, он ограничен по размеру стека.

Стек также не сжимается (очевидно), потому что он «перемещает указатель стека вниз в новое пространство» при каждом объявлении переменной.

Типичные размеры стеков на современных настольных компьютерах и серверах составляют 8 МБ в Linux / OSX и 1 МБ в Windows. Они могут быть скорректированы. Размеры кучи (куда направляются векторы) ограничены только физической памятью в машине (фактически, виртуальной памятью, если вы не против переместиться на диск) Так обычно несколько ГБ.

Это неплохая статья на эту тему. https://www.tutorialspoint.com/cplusplus/cpp_dynamic_memory.htm

Но имейте в виду, что в нем много говорится о new и delete. 99% времени вы не должны использовать их. Они произойдут «автоматически» внутри реализации конструктора и деструктора std::vector (и еще нескольких мест).

4
Oliver Schönrock 20 Ноя 2019 в 17:40

std::vector<T> выделяет память во время выполнения. ОС предоставляет ему большой блок памяти, который находится где-то еще в адресном пространстве, и std::vector содержит только указатель (адрес) на него, поэтому sizeof(std::vector<T>) всегда имеет некоторый фиксированный размер и не будет заполнять следующая вещь в стеке.

Когда вы отодвигаете достаточно элементов назад, реализации std::vector обычно выделяют новый буфер памяти и копируют всю старую память. Таким образом, память остается непрерывной, даже если в ее буфере не хватает места. Это влечет за собой небольшое наказание за растущие векторы элемент за элементом, поэтому, если вы знаете, какой это будет размер, my_vector.reserve(N) позаботится о том, чтобы на нем было достаточно места для N элементов без перераспределения.

std::array<T, N> больше похоже на то, как вы думаете, как C массив, где вся память является частью объекта. Из-за этого std::array не может быть изменен.

3
parktomatomi 20 Ноя 2019 в 17:03