Вопрос

Я довольно новый к C ++, но я знаю, что вы не можете просто использовать память Willy Nilly, как STD :: String Class, кажется, позволяет вам делать. Например:

std::string f = "asdf";
f += "fdsa";

Как ручка класса String становится больше и меньше? Я предполагаю, что он выделяет количество памяти по умолчанию, и если ему нужно больше, это newБольшая часть памяти и копирует себя к этому. Но не будет ли это довольно неэффективным, чтобы придеться скопировать всю строку каждый раз, когда нужно было изменять размер? Я не могу думать о том, что он может быть сделан (но, очевидно, кто-то сделал).

И в этом отношении, как все классы Stdlib, как вектор, очередь, стек, ручка и т. Д., Растущее и сокращаяся так прозрачно?

Это было полезно?

Решение

Обычно есть удвоенный алгоритм. Другими словами, когда он заполняет текущий буфер, он выделяет новый буфер, который в два раза больше, а затем копирует текущие данные. Это приводит к меньшему количеству выделения / копирования операций, чем альтернатива роста одним блоком распределения.

Другие советы

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

Контейнеры также обычно пытаются смягчить влияние частых переоценовения путем выделения большего количества воспоминаний, чем им нужно. Обычный алгоритм - это то, что когда строка находит, что это не имеет места, это удваиваться его размер буфера вместо того, чтобы просто выделить минимальный, необходимый для удержания нового значения. Если строка выращивается один символ за раз, этот алгоритм удвоения уменьшает временную сложность для амортизированного линейного времени (вместо квадратичного времени). Это также уменьшает восприимчивость программы к фрагментации памяти.

Хотя я не знаю точную реализацию STD :: string, большинство структур данных, которые необходимо обрабатывать динамический рост памяти, делают это, делая именно то, что вы говорите - выделите объем памяти по умолчанию, и если больше необходимо, чтобы создать больший блок и скопируйте себя.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top