Много хороших ответов, но я чувствую, что чего-то не хватает в отношении того, «почему нам нужно выделять память». Я думаю, что важно знать, как поток управления компьютерной программы работает на самом низком уровне, поскольку C и C ++ являются относительно тонкими слоями абстракции над аппаратным обеспечением.
Хотя можно написать программу в одной огромной глобальной области с использованием только ifs и gotos, большинство реальных программ разбиты на функции , которые представляют собой отдельные подвижные модули, которые могут вызывать друг друга в будут. Чтобы отслеживать все данные (аргументы, возвращаемое значение, локальные переменные), все эти данные помещаются в одномерную непрерывную область памяти, называемую стек . Вызов функции помещает вещи в стек, а возвращение из функции отбрасывает данные обратно, и та же область памяти перезаписывается при следующем вызове функции.
Таким образом, весь код функции может быть сохранен абстрактно, просто запомнив смещения к локальным данным относительно их точки входа, и одна и та же функция может быть вызвана из многих различных контекстов - локальные переменные функции могут находиться по разным абсолютным адресам, но они всегда находятся в одном и том же относительном положении относительно адреса входа в функцию.
Тот факт, что память стека постоянно перезаписывается при вызове и возврате функций, означает, что вы не можете поместить какие-либо постоянные данные в стек, т. Е. В локальную переменную, поскольку память для локальных переменных не сохраняется неизменной после функции возвращается. Если вашей функции нужно где-то хранить постоянные данные, она должна хранить эти данные в другом месте. Это другое расположение - так называемая heap , для которой вы вручную (также называемый «динамически») запрашиваете постоянное хранилище через malloc
или new
. Эта область памяти находится в другом месте и не будет перезаписана или перезаписана никем, и вы можете безопасно передавать указатель на эту память столько, сколько захотите. Единственным недостатком является то, что если вы вручную не сообщите системе, что вы сделали, она не сможет использовать память для чего-то еще, поэтому вы должны вручную очистить эту динамически распределенную память. Но необходимость в функциях для хранения постоянной информации является причиной, по которой нам нужно выделять память.
(Просто для завершения картины: локальные переменные в стеке называются «автоматически распределенными». Существует также «статическое распределение», которое происходит во время компиляции и где живут глобальные переменные. Если у вас есть глобальные char[30000]
, вы можете с радостью читать и писать в нее из любой точки вашей программы.)