Хотя я не знаю точной реализации std :: string, большинство структур данных, которые должны обрабатывать динамический рост памяти, делают это именно так, как вы говорите - выделяете объем памяти по умолчанию, и, если требуется больше, создайте большой блок и скопировать себя.
Способ обойти очевидную проблему неэффективности состоит в том, чтобы выделить больше памяти, чем вам нужно. Соотношение используемой памяти: общая память вектора / строки / списка / и т. Д. Часто называют коэффициент загрузки (также используется для хеш-таблиц в несколько ином значении). Обычно это соотношение 1: 2, то есть вы выделяете вдвое больше необходимой памяти. Когда у вас заканчивается свободное пространство, вы назначаете новый объем памяти в два раза больше текущего и используете его. Это означает, что со временем, если вы продолжите добавлять вещи в вектор / строку / и т. Д., Вам придется копировать элемент все меньше и меньше (поскольку создание памяти экспоненциально, а вставка новых элементов, конечно, линейна), и поэтому время, затрачиваемое на этот метод обработки памяти, не так велико, как вы думаете. Согласно принципам Амортизированный анализ , вы можете видеть, что вставка m
элементов в вектор / строку / список с использованием этого метода - это только Big-Theta из m, а не m 2 .