Раньше я думал, что люди делятся на два типа: те, кто понимает указатели и те, кто их не понимает. А оказалось, люди делятся на два других типа: те, кто может объяснить указатели и те, кто нет.
Если выбросить из C++ указатели, и другие, не столь важные низкоуровневые конструкции, мы получим подобие одного из более поздних императивных языков: C#, Java. Непонимание указателей - основной барьер в изучении C++. К счастью, не для нас.
Как уже много раз упоминалось ранее, вся ОЗУ разбита на пронумерованные ячейки размером в один байт. Переменные, что нам доводилось с Вами создавать, были локальными переменными. Локальность их заключалась во времени жизни. Время жизни локальной переменной - блок кода, в котором объявлена такая переменная(код, заключенный в фигурные скобки, будь-то тело условия, цикла или функции).
int main()
{
int32_t a;
{
int8_t b;
{
int16_t c;
}
}
return 0;
}
Сначала создастся переменная "a". Затем переменная "b" и только потом "c". Но! Будьте внимательны! Сначала истечет время жизни переменной "c", затем будет разрушена переменная "b" и лишь потом "a". Такая модель создания-удаления переменных называется First In First Out(FIFO). Это в свою очередь и описывает работу стека. В данном контексте, стек - участок памяти, отведенный под локальные переменные. Размер стека по умолчанию небольшой: несколько мегабайт. Обычно, этого хватает с головой. Если Вам вдруг станет недоставать размера стека по умолчанию(по обоснованным причинам), то Вы уже будете на том уровне, где помощь с его увеличением от меня не потребуется. Вторая интересная вещь: чтобы управлять стеком, достаточно лишь иметь доступ к его верхушке. Представим, что изначально верхушка стека указывала на ячейку с номером 100 и смоделируем его работу из нашего простенького примера.
Стек был пуст:
stack
[...] 103
[ ] 102
[ ] 101
[ ] 100
[...] 99
Мы объявили локальную переменную "a", что заняла место четырех байт с 100 по 103 включительно. Верхушкой стека стал адрес 104. Когда мне вздумается объявить новую переменную, свободное место в памяти не придется искать, ведь вершина стека известна выполняемой среде.
stack [...] 105
[ ] 104
[ ] 103
[ ] 102
[ ] 101
[ ] 100 = a
[...] 99
Объявление переменной "b", состоящей всего из одного байта:
stack [...] 106
[ ] 105
[ ] 104 = b
[ ] 103
[ ] 102
[ ] 101
[ ] 100 = a
[...] 99
Верхушка сдвинулась на адрес с номером 105. Создание последней переменной по аналогии:
stack [...] 108
[ ] 107
[ ] 106
[ ] 105 = c
[ ] 104 = b
[ ] 103
[ ] 102
[ ] 101
[ ] 100 = a
[...] 99
Как гласит правило работы стека: первым вошел - последним вышел. Так у нас и случилось. Переменные попали в стек в очередности "a", "b", "c", но удалятся из него в обратном порядке: "c", "b", "a". Ничего принципиально нового этот урок не учит, ведь объявляя переменные, Вы сами того не подозревая, использовали стек.
Выводы: принцип работы стека прост, но весьма эффективен. Стек работает быстро, но его одного не хватит для решения большинства задач и об этом в следующей главе.
Если выбросить из C++ указатели, и другие, не столь важные низкоуровневые конструкции, мы получим подобие одного из более поздних императивных языков: C#, Java. Непонимание указателей - основной барьер в изучении C++. К счастью, не для нас.
Как уже много раз упоминалось ранее, вся ОЗУ разбита на пронумерованные ячейки размером в один байт. Переменные, что нам доводилось с Вами создавать, были локальными переменными. Локальность их заключалась во времени жизни. Время жизни локальной переменной - блок кода, в котором объявлена такая переменная(код, заключенный в фигурные скобки, будь-то тело условия, цикла или функции).
int main()
{
int32_t a;
{
int8_t b;
{
int16_t c;
}
}
return 0;
}
Сначала создастся переменная "a". Затем переменная "b" и только потом "c". Но! Будьте внимательны! Сначала истечет время жизни переменной "c", затем будет разрушена переменная "b" и лишь потом "a". Такая модель создания-удаления переменных называется First In First Out(FIFO). Это в свою очередь и описывает работу стека. В данном контексте, стек - участок памяти, отведенный под локальные переменные. Размер стека по умолчанию небольшой: несколько мегабайт. Обычно, этого хватает с головой. Если Вам вдруг станет недоставать размера стека по умолчанию(по обоснованным причинам), то Вы уже будете на том уровне, где помощь с его увеличением от меня не потребуется. Вторая интересная вещь: чтобы управлять стеком, достаточно лишь иметь доступ к его верхушке. Представим, что изначально верхушка стека указывала на ячейку с номером 100 и смоделируем его работу из нашего простенького примера.
Стек был пуст:
stack
[...] 103
[ ] 102
[ ] 101
[ ] 100
[...] 99
Мы объявили локальную переменную "a", что заняла место четырех байт с 100 по 103 включительно. Верхушкой стека стал адрес 104. Когда мне вздумается объявить новую переменную, свободное место в памяти не придется искать, ведь вершина стека известна выполняемой среде.
stack [...] 105
[ ] 104
[ ] 103
[ ] 102
[ ] 101
[ ] 100 = a
[...] 99
Объявление переменной "b", состоящей всего из одного байта:
stack [...] 106
[ ] 105
[ ] 104 = b
[ ] 103
[ ] 102
[ ] 101
[ ] 100 = a
[...] 99
Верхушка сдвинулась на адрес с номером 105. Создание последней переменной по аналогии:
stack [...] 108
[ ] 107
[ ] 106
[ ] 105 = c
[ ] 104 = b
[ ] 103
[ ] 102
[ ] 101
[ ] 100 = a
[...] 99
Как гласит правило работы стека: первым вошел - последним вышел. Так у нас и случилось. Переменные попали в стек в очередности "a", "b", "c", но удалятся из него в обратном порядке: "c", "b", "a". Ничего принципиально нового этот урок не учит, ведь объявляя переменные, Вы сами того не подозревая, использовали стек.
Выводы: принцип работы стека прост, но весьма эффективен. Стек работает быстро, но его одного не хватит для решения большинства задач и об этом в следующей главе.
Комментариев нет:
Отправить комментарий