Мне просто понравился вопрос и сделал некоторые эксперименты самостоятельно, используя компилятор MSVC14
(оптимизация отключена).
C++, 11/14 имеет следующие контейнеры последовательности (преднамеренно исключены dynarry
, введенные в С ++ 14):
- Нет динамического изменения размера (до программиста, чтобы выделить и DEALLOCATE)
- Raw массив (например,
int char[]
)
- Массив (например,
new array<int, size>(){...}
)
- С динамическое изменение размера
- Vector (последовательное выделение памяти)
- список (связанный список как массив)
- forward_list (подобный список)
- Deque (двусвязная очередь)
Позвольте мне начать с вопросов,
the solution of allocating a new array with a size+1, and then copying all the current elements into it and reading a new element, but I find that this would be a brutal waste of processing time and memory
Вы правы, но для уменьшения накладных расходов, при выделении памяти для использования и затем выяснить, что вам нужно больше памяти, чем выделенные, вам нужно выделить новую память и скопируйте предыдущие данные, затем освободите предыдущую выделенную память.
Но подождите! Сколько выделяется (размер + 1 плохо)? Каждый раз, когда вы вынуждены выделять больший объем памяти, вам лучше выделять в два раза больше того размера, который у вас уже был в руках, чтобы вы уменьшили вероятность повторного распределения памяти; потому что считается чрезвычайно дорогостоящей операцией.
if it is possible to simply allocate the next memory address and use it for my array. Is there a way to do that in C++?
Это не полностью под вашим контролем, поскольку среда выполнения C++ реализовала функции управления памятью. Если ваша вновь выделенная память будет, не находится под вашим контролем, однако иногда бывает так, что новое выделенное пространство будет иметь тот же базовый адрес, что и предыдущий; это зависит от времени выполнения и от memory fragmentation.
Я получил некоторые тесты с использованием malloc
и realloc
функций заимствованы из C. Вот код: (. Для вставки 100000000 целых чисел, время в среднем 3 прогонов)
auto start = chrono::steady_clock::now();
auto partialSize = 100;
auto arr = (int *) malloc(sizeof(int) * partialSize);
for (auto i = 0; i < SIZE; i++) {
arr[i] = i;
if (i == partialSize - 1) {
partialSize = partialSize << 1; // for 2X
arr = (int *) realloc(arr, sizeof(int) * partialSize);
}
}
auto duration = chrono::steady_clock::now() - start;
free(arr);
cout << "Duration: " << chrono::duration_cast<chrono::milliseconds>(duration).count() << "ms" << endl;
Результаты:
- Start Размер = 100, инкремент Steps = 1.5X, Time (s) = 1.35s
- Start Размер = 100, инкремент Steps = 2X, Time (s) = 0.65s
Start Размер = 100, инкремента Steps = 4X, Time (s) = 0.42s
Start Size = 10000, инкремента Steps = 1.5X, Time (s) = 0.96s
- Start Size = 10000, инкремент Steps = 2X, Time (s) = 0.79s
Start Размер = 10000, инкремент шаги = 4X, Time (s) = 0.51s
Другого случая использование C++ 's new
ключевого слова и проверку перемещения :
auto start = chrono::steady_clock::now();
auto partialSize = 100;
auto arr = new int[partialSize];
for (auto i = 0; i < SIZE; i++) {
arr[i] = i;
if (i == partialSize - 1) {
auto newArr = new int[partialSize << 2]; // for 4X
partialSize = partialSize << 2;
arr = newArr;
}
}
auto duration = chrono::steady_clock::now() - start;
delete[] arr;
cout << "Duration: " << chrono::duration_cast<chrono::milliseconds>(duration).count() << "ms" << endl;
Результаты (для вставки 100 000 000 целых чисел; время - среднее. из 3 пробегов):
- Начальный размер = 100, приращение шагов = 1.5X, время (ы) = 0.63S
- Start Размер = 100, инкремент Steps = 2X, Time (s) = 0.44s
Start Размер = 100, инкремент Steps = 4X, Time (s) = 0.36s
Start Size = 10000, инкремент Steps = 1.5X, Time (s) = 0.65s
- Start Size = 10000, инкремент Steps = 2X, Time (s) = 0.52s
- Start Size = 10000, инкремент Steps = 4X, время (ы) = 0,42 с
Для остальных (контейнеры с изменяемой динамической способностью):
auto start = chrono::steady_clock::now();
//auto arr = vector<int>{};
//auto arr = list<int>{};
//auto arr = new std::array<int, SIZE>{};
//auto arr = new int[SIZE];
//auto arr = deque<int>{};
auto arr = forward_list<int>{};
for (auto i = 0; i < SIZE; i++) {
arr.push_front(i);
// arr.push_back(i)
}
auto duration = chrono::steady_clock::now() - start;
cout << "Duration: " << chrono::duration_cast<chrono::milliseconds>(duration).count() << "ms" << endl;
Результаты (для вставки 100 000 000 целых чисел; время - среднее. от 3 работает):
вектор
список
массив (без Перераспределение)
- Время (с) = N/A; Ошибка: компилятор из кучи.
сырья INT массива (без Перераспределение)
Deque
forward_list
Надеется, что это помогает.
Используйте 'std :: vector'. – tkausl
Если вы хотите использовать 'new', тогда вам нужно сделать это, прежде чем читать в пространстве ... –
Спасибо, но я подумал об этом, конечно. По причинам, которые не важны для этого обсуждения, я не могу это использовать. –