Стек и куча
Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy. Урок 12 из 104.
Программы на C++ используют две основные области памяти: стек и heap. Понимание того, где находятся ваши объекты, имеет решающее значение для написания эффективного кода без ошибок.
Стек — это быстрая автоматическая память. Переменные, объявленные внутри функций, хранятся здесь и автоматически уничтожаются, когда выходят из области видимости.
void example() {
int x = 10; // Выделение в стеке
Player player; // Выделение в стеке — уничтожается автоматически
} // x и player уничтожаются здесьheap — это более крупная, но медленная memory, которой ты управляешь вручную. Объекты в heap сохраняются, пока ты явно не выполнишь delete их.
void example() {
Player* player = new Player(); // Выделение в куче
// player существует до удаления
delete player; // Требуется ручная очистка
}Ключевые различия:
| Stack | Heap |
|---|---|
| Быстрое выделение | Более медленное выделение |
| Ограниченный размер | Большая ёмкость |
| Автоматическая очистка | Требуется Manual cleanup |
| Объекты фиксированного размера | Объекты динамического размера |
Используйте выделение памяти в стеке для небольших объектов с коротким временем жизни. Используйте выделение памяти в куче, когда объекты должны пережить свою область видимости или когда их размер определяется во время выполнения.
Забывание удалить память в куче вызывает утечки памяти — распространённый источник ошибок в программах на C++.
Задание
ЛегкоДавайте исследуем разницу между стековой и кучевой памятью, создав простой класс Counter, который отслеживает, как объекты создаются и уничтожаются.
Вы создадите два файла, чтобы организовать свой код:
Counter.h: define классCounterс атрибутомnameprivate (строка). Включите constructor, который принимает имя и выводит"Creating: <name>", а также destructor, который выводит"Destroying: <name>". Добавьте methodgetName(), возвращающий имя счётчика.main.cpp: продемонстрируйте выделение памяти как в стеке, так и в куче. Прочитайте имя из input, затем:- Create размещённый в стеке
Counter, используя это имя - Create размещённый в куче
Counterс именем"HeapCounter" - Выведите оба имени счётчиков в формате
"Stack: <name>"и"Heap: <name>" - Delete размещённый в куче счётчик, чтобы prevent утечку memory
- Create размещённый в стеке
Обратите внимание, как сообщения constructor и destructor появляются в разном порядке в зависимости от того, когда вы создаёте и удаляете каждый объект. Объект в стеке будет automatically уничтожен, когда завершится main(), тогда как объект в куче необходимо удалить явно.
Подключите header-файл в main.cpp, используя #include "Counter.h".
Попробуйте сами
#include <iostream>
#include <string>
#include "Counter.h"
using namespace std;
int main() {
// Прочитать имя из ввода
string inputName;
cin >> inputName;
// TODO: Создать выделенный в стеке Counter, используя inputName
// TODO: Создать выделенный в куче Counter с именем "HeapCounter"
// TODO: Print stack counter name in format "Stack: <name>"
// TODO: Вывести имя счётчика в куче в формате "Heap: <name>"
// TODO: Удалить выделенный в куче счётчик, чтобы предотвратить утечку памяти
return 0;
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыСборка и компиляция C++Заголовочные файлы и файлы исходного кодаПространства имен и область видимостиВведение в ООП на C++Классы и объектыУказатель 'this'Методы (функции-члены)Атрибуты (члены данных)Основы конструкторов и деструкторовИтоги — Простой калькулятор4Свойства классов
Члены экземпляра против статическихГеттеры и сеттерыКонстантные функции-членыКлючевое слово mutableСтатические методы и переменныеДружественные функции и классыИтоги — Менеджер банковских счетов7Наследование
Основы наследованияУровни доступа при наследованииПорядок вызова конструкторов и деструкторовПереопределение методовВиртуальные функции и VTableМножественное наследованиеВиртуальное наследованиеИтоги — Иерархия сотрудников10Обзор STL
Обзор и философия STLКонтейнеры STLИтераторыАлгоритмы STLФункторы и лямбда-выраженияИтоги: частота слов13Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonFactory и Abstract FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy2Управление памятью
Стек и кучаУказатели и ссылкиДинамическая память (new/delete)Умные указатели в C++RAII в C++Итоги — Менеджер динамического массива5Инкапсуляция
Спецификаторы доступа в C++Спецификаторы доступа: подробный разборСокрытие данныхStruct против ClassВложенные и внутренние классыИтоги — Система учета студентов8Полиморфизм
Полиморфизм компиляции и времени выполненияПерегрузка функцийВиртуальные функции: повторениеЧистые виртуальные функцииАбстрактные классыПроектирование интерфейсов на C++Dynamic Casting и RTTIИтоги: Калькулятор фигур11Продвинутые концепции ООП
Композиция против наследованияМиксины через CRTPИдиома PimplСтирание типовEnum Classes и строгая типизацияОбработка исключений в ООППользовательские иерархии исключений14Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикRAII как паттерн3Конструкторы и деструкторы
Конструктор по умолчаниюПараметризованный конструкторКонструктор копированияКонструктор перемещенияСписки инициализации конструктораДелегирующие конструкторыГлубокое погружение в деструкторыПравило трех / пяти / нуляПовторение — класс String6Перегрузка операторов
Введение в перегрузку операторовПерегрузка арифметических операторовПерегрузка операторов сравненияОператоры потоковПерегрузка оператора присваиванияПерегрузка операторов [] и ()Операторы преобразования типовИтоги — класс Matrix9Шаблоны
Шаблоны функцийШаблоны классовСпециализация шаблоновВариативные шаблоныОсновы SFINAE и Type TraitsИтоги — Обобщенный контейнерПотренируйтесь самостоятельно: Онлайн-компилятор C++