А мне хотя бы придумать, как можно дополнять массив, чтобы потом быстро к нему обращаться.
Для этого вам придётся отказаться от того, чтобы содержать его в виде массива. Например, можно организовать множество кусков, каждый из которых многоэлементный как массив, а сами куски организованы в список или дерево - за счёт небольшого числа кусков, доступ к нужному куску будет быстрый. Но в стандартных библиотеках такого нет, надо реализовать самому, впрочем, на основе имеющихся
std::vector,
std::list,
std::map/set это делается легко и непринуждённо.
Кроме того, надо подумать, а нужно ли вам при этом всё держать в массиве.
std::map может вас вполне устраивать. И разумеется, код надо писать так, чтобы сменить тип контейнера при необходимости можно было легко, не переделывая всего написанного.
Пока представляется так: статическим объектам память выделяется сразу, динамическим объектам память выделяется большими кусками, причем достаточно большая, чтобы объекты влазили в нее целиком, в результате скорость доступа максимально.
С точки зрения языка (и программиста) динамическому объекту выделяется ровно столько памяти, сколько ему нужно. Статический (в смысле
static) объект размещается ещё на этапе компиляции и загрузки, в отдельном разделе статических данных. Автоматический (
auto) - в момент входа в блок (в Си) или выполнения объявления объекта (C++), в стеке.
Рекомендуется почитать про объектные и загрузочные форматы, работу линкера и загрузчика, работу стека при входе/выходе из функций. Распределение памяти - тема, опирающаяся на этот background. То есть, конечно, в детали она не лезет, но по крайней мере отсюда следует, с какими запросами имеет дело система памяти ОС.
Хотя вроде есть намеки на то, что иногда объект разбивается в памяти на куски.
Это только в случае, если язык позволяет это делать, не предоставляет пользователю слишком низкоуровневого доступа к структуре данных. Например, C++ такого не позволяет никогда. А какой-нибудь APL - может запросто. Или PHP.
скорость доступа возрастает до
Не скорость доступа возрастает, а время доступа возрастает :-) А скорость - падает.
3. Опять делаем 2 массива. Опять в 1-м храним имена переменных и массивов и номер ячейки памяти, с которых они начинаются. Во 2-м массиве для каждого массива выделяем на 1-м шаге

ячеек, а на

-м

ячеек. В результате будет

, скорость доступа

и выделение памяти работает за

. (этот алгоритм меня особенно радует)
Именно так все и делают, но к сожалению, вы неправильно оценили характеристики. Время доступа как раз

а время выделения памяти амортизированно

но если массив попал на границу размера

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

ячеек, а с существенной задержкой, например, когда он достигнет размера

С другой стороны, мне сказали, что в C++.net есть какие-то двойные списки, в которых 2-й аргумент может быть произвольным типом. TList и THashMap вроде. Если найду, наверное буду их использовать. Неохота мучиться...
Не знаю, что там в C++.net, а в стандартной библиотеке C++ есть и
std::list, и
std::map, а в новой редакции стандарта - и хэш-таблицы
std::unordered_map (если вы работаете в старой версии, используйте хэш-таблицы из Boost-а
boost::unordered_map).
Если найду, наверное буду их использовать. Неохота мучиться...
Так бы сразу и использовали стандартные контейнеры, зачем всё это накручивать?
Ну может кто-то уже набил шишки и написал книжку о шишках, которую я прочту.
Это хорошо бы, но шишки у всех разные, индивидуальные.
Наконец, можно и в голове поперебирать, это не всегда сложно.
Нет, пока до реализации дело не дойдёт, заранее угадать, на чём будут шишки, нельзя.