Урок №51. Статические переменные

  Юрий  | 

  |

  Обновл. 13 Сен 2021  | 

 127506

 ǀ   23 

Ключевое слово static является одним из самых запутанных в языке C++. Оно имеет разные значения в разных ситуациях.

На уроке о глобальных переменных мы узнали, что, добавляя static к переменной, объявленной вне блока, мы определяем её как внутреннюю, то есть такую, которую можно использовать только в файле, в котором она определена.

Ключевое слово static можно применять и к переменным внутри блока, но тогда его значение будет другим. На уроке о локальных переменных мы узнали, что локальные переменные имеют автоматическую продолжительность жизни, т.е. создаются, когда блок начинается, и уничтожаются при выходе из него.

Использование ключевого слова static с локальными переменными изменяет их свойство продолжительности жизни с автоматического на статическое (или «фиксированное»). Статическая переменная (или «переменная со статической продолжительностью жизни») сохраняет свое значение даже после выхода из блока, в котором она определена. То есть она создается (и инициализируется) только один раз, а затем сохраняется на протяжении выполнения всей программы.

Рассмотрим разницу между переменными с автоматической и статической продолжительностями жизни.

Автоматическая продолжительность жизни (по умолчанию):

Каждый раз, при вызове функции incrementAndPrint(), создается переменная value, которой присваивается значение 1. Функция incrementAndPrint() увеличивает значение переменной до 2, а затем выводит его. Когда incrementAndPrint() завершает свое выполнение, переменная выходит из области видимости и уничтожается.

Следовательно, результат выполнения программы:

2
2
2

Теперь рассмотрим статическую версию. Единственная разница между этими двумя программами только в добавлении ключевого слова static к переменной.

Статическая продолжительность жизни:

Поскольку переменная s_value объявлена статической (с помощью ключевого слова static), то она создается и инициализируется только один раз. Кроме того, выходя из области видимости, она не уничтожается. Каждый раз, при вызове функции incrementAndPrint(), значение s_value увеличивается.

Результат выполнения программы:

2
3
4

Так же, как мы используем префикс g_ с глобальными переменными, префикс s_ принято использовать со статическими переменными. Обратите внимание, внутренние глобальные переменные (которые объявлены с использованием static) остаются с префиксом g_, а не с префиксом s_.

Зачем нужны статические локальные переменные? Одним из наиболее распространенных применений является генерация уникальных идентификаторов. При работе с большим количеством одинаковых объектов внутри программы часто бывает полезно присвоить каждому объекту отдельный уникальный идентификационный номер. Это легко осуществить, используя одну статическую локальную переменную:

При первом вызове функции возвращается 0. Во второй раз возвращается 1. Затем 2 и каждый последующий вызов будет увеличивать эту переменную на единицу. Хороший способ генерации уникальных идентификаторов для похожих объектов? Хороший! Поскольку s_itemID — это локальная переменная, то она не может быть «изменена» другими функциями.

Статические переменные имеют некоторые преимущества глобальных переменных (они не уничтожаются до завершения программы), сохраняя при этом локальную область видимости. Таким образом, они намного безопаснее для использования, нежели глобальные переменные.

Тест

Какой эффект от добавления ключевого слова static к глобальной переменной? Какое влияние оно имеет на локальную переменную?

Ответ

Добавляя ключевое слово static к глобальной переменной, мы определяем её как внутреннюю, то есть такую, которую нельзя экспортировать и использовать в других файлах.

В случае с локальной переменной, добавление static определяет её как статическую, то есть она создается и инициализируется только один раз, и не уничтожается до самого конца программы.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (591 оценок, среднее: 4,93 из 5)
Загрузка...

Комментариев: 23

  1. Саша:

    А если вернуть адрес статической переменной, а примет ее константная ссылка?
    Не оч понял тему про время компиляции и работы, но говорилось, что константная ссылка продлевает время жизни переменной

  2. Никита:

    То есть, если такую переменную создать внутри блока функции main, то значение будет существовать, но доступа к переменной не будет даже для чтения? (Понимаю, что тогда такая переменная бесполезна, но мне для восприятия информации необходимо понять это)

    1. Fantasy:

      Суть же не в том чтоб создавать «бесполезный функционал» одно изменение поведения переменных с помощью статика уже что-то. Если честно не вижу смысла в создании её в блоке ф-к майн если её польза раскрывается в повторных вызовах, думаю любая команда может быть бесполезной в некоторых случаях, но это не делает их ненужными.

    2. Владимир:

      То есть, если такую переменную создать внутри блока функции main, то значение будет существовать, но доступа к переменной не будет даже для чтения?

      Что-то я такого в тексте урока не увидел. По-моему доступ для чтения будет. Во всяком случае внутри блока.

  3. ОЛЕГ:

    Очень интересная тема. Не удержался и, с использованием статической локальной переменной, написал программу вычисляющую на каком расстоянии от земли будет космический корабль с космонавтами в течение 10 секунд (посекундно) от начала старта от земли. Ускорение 5g (g равно 9,81 ). Формула — S=a*t^2/2.

    main.ccp:

    1. DeniZZka:

      Через for было бы практичнее.

      1. Grave18:

        В космосе только так, циклы ненадежные)

        1. Fantasy:

          Объективно бред, через цикл сделать код будет лучше и целесообразней.

           

  4. Стас:

    А может ли быть смысл в таком выражении

    ?

    1. Андрей:

      Во-первых, константы по умолчанию являются статическими. Во-вторых, если бы это было не так, это просто бессмысленное выражение, потому-что если вы хотите, чтобы константы в неймспейсе были видны только в этом файле, то сделайте сам неймспейс статическим. А если нет — то зачем тогда скрывать отдельные константы.

      1. Сергей:

        "Во-первых, константы по умолчанию являются статическими."

        А вот с этого места поподробнее. Где это написано в стандарте?

      2. Саша:

        Вы наверное имели ввиду внутренними?
        Если нет, можно поподробнее)

  5. AHTOH:

    static внутри блока? Это то что мне всегда не хватало и приходилось заводить глобальную переменную.
    1. Инитится 1 раз. (при следующем заходе игнорируется)
    2. Сохраняет предыдущее значение. (т.е. ведет себя как глобальная переменная, но при этом недоступна вне блока. Что собственно позволяет не беспокоиться о ее целостности.

    ЗЫ. Почему то раньше в других языках я не встречал такой подход.

  6. Misha_81:

    Статические локальные переменные в функции очень напомнили термин "Замыкание" в javascrip.

  7. Slava:

    Очень хорошие уроки, начал читать затянулся. Сколько искал, гуглил, чтобы выучить язык, смотрел видео. Но данный сайт топ. Спасибо вам за вашу роботу Юрий.

  8. Олег:

    Весьма толково. Уже написал прогу высчитывания разверток…. Удобно. Очень Вам благодарен….

  9. Андрец:

    Юрий, спасибо большое за эти уроки! Ну просто огромнейшее спасибо!

    1. Фото аватара Юрий:

      Большое пожалуйста 😉

  10. Ильдар:

    Поддерживаю одобрения об этом сайте и вашей работе.

    По поводу урока: локальная переменная будет "жить" до конца, но и в тоже время изменять её можно только в блоке, в котором она была создана, верно?

  11. Sergey:

    Полезные уроки.
    Можно быстро найти ответ на интересующий вопрос, не вникая в талмуды.
    Спасибо.

    1. Фото аватара Юрий:

      Пожалуйста)

  12. Malkin:

    Честно скажу, это лучшие уроки вообще в рунете из всего, что я гуглил много лет. Поскольку занимаюсь МК и ассемблером, важно было узнать, что происходит с памятью в процессе Си кода — стек, куча, все дела. Везде пишут, лишь как правильно писать код, а здесь автор объясняет всю поднаготную, особенно в дальнейших уроках. Бесконечно благодарен!

    1. Фото аватара Юрий:

      Пожалуйста, мне очень приятно))

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *