Для создания переменных, доступных во всех файлах программы, используется класс памяти
Обновлено: 24.11.2024
В этом разделе мы обсудим использование ключевого слова static для создания полей и методов, принадлежащих классу, а не экземпляру класса.
Переменные класса
Когда на основе одного и того же класса создается несколько объектов, каждый из них имеет свои собственные отдельные копии переменных экземпляра. В случае класса Bicycle переменными экземпляра являются cadence, gear и speed. Каждый объект Bicycle имеет собственные значения этих переменных, хранящиеся в разных местах памяти.
Иногда вам нужны переменные, общие для всех объектов. Это достигается с помощью статического модификатора. Поля, в объявлении которых есть модификатор static, называются статическими полями или переменными класса. Они связаны с классом, а не с каким-либо объектом. Каждый экземпляр класса совместно использует переменную класса, которая находится в одном фиксированном месте в памяти. Любой объект может изменить значение переменной класса, но переменными класса также можно манипулировать без создания экземпляра класса.
Например, предположим, что вы хотите создать несколько объектов Bicycle и присвоить каждому серийный номер, начиная с 1 для первого объекта. Этот идентификационный номер уникален для каждого объекта и поэтому является переменной экземпляра. В то же время вам нужно поле для отслеживания того, сколько объектов Bicycle было создано, чтобы вы знали, какой ID присвоить следующему. Такое поле относится не к какому-либо отдельному объекту, а к классу в целом. Для этого вам понадобится переменная класса numberOfBicycles следующим образом:
На переменные класса ссылается само имя класса, как в
Это дает понять, что они являются переменными класса.
Вы можете использовать конструктор Bicycle, чтобы установить переменную экземпляра id и увеличить переменную класса numberOfBicycles:
Методы класса
Язык программирования Java поддерживает как статические методы, так и статические переменные. Статические методы, которые имеют модификатор static в своих объявлениях, должны вызываться с именем класса без необходимости создания экземпляра класса, как в
Статические методы обычно используются для доступа к статическим полям. Например, мы могли бы добавить статический метод в класс Bicycle для доступа к статическому полю numberOfBicycles:
Разрешены не все комбинации переменных и методов экземпляра и класса:
- Методы экземпляра могут напрямую обращаться к переменным экземпляра и методам экземпляра.
- Методы экземпляра могут напрямую обращаться к переменным и методам класса.
- Методы класса могут напрямую обращаться к переменным и методам класса.
- Методы класса не могут напрямую обращаться к переменным или методам экземпляра — они должны использовать ссылку на объект. Кроме того, методы класса не могут использовать ключевое слово this, так как нет экземпляра, на который можно ссылаться.
Константы
Модификатор static в сочетании с модификатором final также используется для определения констант. Модификатор final указывает, что значение этого поля не может измениться.
Например, следующее объявление переменной определяет константу с именем PI , значение которой является приближенным числом пи (отношением длины окружности к ее диаметру):
Константы, определенные таким образом, не могут быть переназначены, и это будет ошибкой времени компиляции, если ваша программа попытается это сделать. По соглашению имена постоянных значений пишутся заглавными буквами. Если имя состоит более чем из одного слова, слова разделяются символом подчеркивания (_).
Примечание. Если примитивный тип или строка определены как константы и значение известно во время компиляции, компилятор заменяет имя константы везде в коде ее значением. Это называется константой времени компиляции. Если значение константы во внешнем мире изменится (например, если законодательно установлено, что число пи на самом деле должно быть равно 3,975), вам потребуется перекомпилировать все классы, использующие эту константу, чтобы получить текущее значение.
Велосипедный класс
После всех изменений, сделанных в этом разделе, класс Bicycle теперь:
Класс хранения определяет область действия (видимость) и время существования переменных и/или функций в программе C++. Эти спецификаторы предшествуют типу, который они модифицируют. Существуют следующие классы хранения, которые можно использовать в программе на C++
Автоматический класс хранения
Класс автоматического хранения является классом хранения по умолчанию для всех локальных переменных.
В приведенном выше примере определены две переменные с одним и тем же классом хранения, auto можно использовать только внутри функций, т. е. локальных переменных.
Класс хранения регистра
Класс хранения регистров используется для определения локальных переменных, которые должны храниться в регистре, а не в ОЗУ.Это означает, что переменная имеет максимальный размер, равный размеру регистра (обычно одно слово), и к ней нельзя применить унарный оператор '&' (поскольку у нее нет ячейки памяти).
Регистр следует использовать только для переменных, требующих быстрого доступа, таких как счетчики. Следует также отметить, что определение «регистра» не означает, что переменная будет храниться в регистре. Это означает, что он МОЖЕТ храниться в регистре в зависимости от ограничений аппаратного обеспечения и реализации.
Статический класс хранения
Статический класс хранения указывает компилятору, что локальная переменная должна существовать в течение всего времени жизни программы, вместо того, чтобы создавать и уничтожать ее каждый раз, когда она попадает в область видимости и выходит из нее. Таким образом, если сделать локальные переменные статическими, они смогут сохранять свои значения между вызовами функций.
Модификатор static также можно применять к глобальным переменным. Когда это делается, область действия этой переменной ограничивается файлом, в котором она объявлена.
В C++, когда static используется для члена данных класса, это приводит к тому, что только одна копия этого члена используется всеми объектами этого класса.
Когда приведенный выше код скомпилирован и выполнен, он дает следующий результат —
Внешний класс хранения
Класс хранения extern используется для предоставления ссылки на глобальную переменную, видимую для ВСЕХ программных файлов. Когда вы используете «extern», переменная не может быть инициализирована, поскольку все, что она делает, это указывает имя переменной на место хранения, которое было определено ранее.
Если у вас есть несколько файлов и вы определяете глобальную переменную или функцию, которая будет использоваться и в других файлах, тогда extern будет использоваться в другом файле для ссылки на определенную переменную или функцию. Просто для понимания extern используется для объявления глобальной переменной или функции в другом файле.
Модификатор extern чаще всего используется, когда есть два или более файла, использующих одни и те же глобальные переменные или функции, как описано ниже.
Первый файл: main.cpp
Второй файл: support.cpp
Здесь ключевое слово extern используется для объявления счетчика в другом файле. Теперь скомпилируйте эти два файла следующим образом —
Это произведет запись исполняемой программы, попробуйте выполнить запись и проверьте результат следующим образом –
Изменяемый класс хранения
Спецификатор mutable применяется только к объектам класса, которые обсуждаются далее в этом руководстве. Он позволяет члену объекта переопределять константную функцию-член. То есть изменяемый член может быть изменен константной функцией-членом.
Класс хранения используется для описания свойств переменной/функции. Эти функции в основном включают область действия, видимость и время жизни, которые помогают нам отслеживать существование конкретной переменной во время выполнения программы.
Язык C использует 4 класса хранения, а именно:
-
Это класс хранения по умолчанию для всех переменных, объявленных внутри функции или блока. Следовательно, ключевое слово auto редко используется при написании программ на языке C. Доступ к автоматическим переменным можно получить только внутри блока/функции, в которой они были объявлены, а не за их пределами (что определяет их область действия). Конечно, к ним можно получить доступ во вложенных блоках родительского блока/функции, в которой была объявлена переменная auto. Тем не менее, к ним можно получить доступ и за пределами их области действия, используя концепцию указателей, представленную здесь, указывая на точное место в памяти, где находятся переменные. Им присваивается значение мусора по умолчанию всякий раз, когда они объявляются.
: Класс хранения Extern просто сообщает нам, что переменная определена в другом месте, а не в том же блоке, где она используется. По сути, значение присваивается ему в другом блоке, и оно также может быть перезаписано/изменено в другом блоке. Таким образом, внешняя переменная — это не что иное, как глобальная переменная, инициализированная допустимым значением, где она объявлена для использования в другом месте. Доступ к нему можно получить из любой функции/блока. Кроме того, обычную глобальную переменную также можно сделать внешней, поместив ключевое слово «extern» перед ее объявлением/определением в любой функции/блоке. В основном это означает, что мы не инициализируем новую переменную, а вместо этого используем/имеем доступ только к глобальной переменной. Основная цель использования внешних переменных заключается в том, что к ним можно получить доступ между двумя разными файлами, которые являются частью большой программы. Для получения дополнительной информации о том, как работают внешние переменные, перейдите по этой ссылке.
: Этот класс хранения используется для объявления статических переменных, которые обычно используются при написании программ на языке C. Статические переменные имеют свойство сохранять свое значение даже после того, как они выходят за пределы своей области видимости! Следовательно, статические переменные сохраняют значение своего последнего использования в своей области.Таким образом, можно сказать, что они инициализируются только один раз и существуют до завершения работы программы. Таким образом, новая память не выделяется, потому что они не объявляются повторно. Их область действия является локальной для функции, для которой они были определены. Доступ к глобальным статическим переменным можно получить в любом месте программы. По умолчанию компилятор присваивает им значение 0.
: Этот класс хранения объявляет регистровые переменные, которые имеют ту же функциональность, что и автоматические переменные. Разница лишь в том, что компилятор пытается сохранить эти переменные в регистре микропроцессора, если доступна свободная регистрация. Это позволяет использовать регистровые переменные намного быстрее, чем использование переменных, хранящихся в памяти во время выполнения программы. Если бесплатная регистрация недоступна, они сохраняются только в памяти. Обычно несколько переменных, к которым в программе требуется очень частый доступ, объявляются с помощью ключевого слова register, что сокращает время работы программы. Здесь следует отметить важный и интересный момент: мы не можем получить адрес регистровой переменной с помощью указателей.
Чтобы указать класс хранения для переменной, необходимо следовать следующему синтаксису:
Синтаксис:
Функции имеют тот же синтаксис, что и приведенный выше для переменных. Взгляните на следующий пример C для дальнейшего пояснения:
Чтобы подробно понять классы хранения и область, сначала нам нужно больше узнать о том, как компилятор/компьютер хранит переменные в памяти компьютера. Для этого мы сначала рассмотрим части памяти программ, затем рассмотрим классы хранения C и то, как класс хранения влияет на область действия переменной и ее размещение в памяти.
Когда программа загружается в память и запускается, для программы резервируется непрерывный раздел виртуальной памяти. В большинстве систем этот раздел памяти можно расширить при необходимости. Мы называем это виртуальной памятью, потому что в действительности память может быть не непрерывной, и на самом деле не вся она может быть загружена в память одновременно. Ответственность за трансляцию между виртуальной памятью и реальной физической памятью лежит на системе подкачки (подкачки памяти) операционной системы, что выходит далеко за рамки этого класса. Насколько известно нашей пользовательской программе, для ее использования доступен непрерывный блок памяти.
При запуске программы двоичный исполняемый файл сначала копируется непосредственно в нижнюю часть блока памяти в два раздела, которые называются разделами текст и данные. Память. Затем резервируется фиксированный объем памяти (количество, определенное компилятором), и значения памяти в этом разделе инициализируются для хранения только нулей. Эта область памяти называется разделом bss. Затем программа переходит к началу нашего доступного блока памяти и начинает выполнение программы. Программа добавляет и удаляет память по мере необходимости из верхней части блока памяти, используя раздел памяти, называемый стеком. По мере того как программа использует больше памяти и стек растет, адрес вершины стека уменьшается. Таким образом, вершина стека фактически имеет самый низкий адрес памяти в стековом разделе памяти. Всякий раз, когда вызывается функция, новые данные проталкиваются или добавляются в стек. Когда функция возвращается, данные стека для функции извлекаются или удаляются из стека. Область между секциями памяти bss и stack называется кучей.
Содержимое разделов памяти можно описать следующим образом:
Текстовая часть программы содержит исполняемые инструкции программы. Таким образом, счетчик инструкций программы представляет собой указатель на текстовую часть. Константы, такие как строковые константы оператора printf(), также хранятся в текстовом разделе памяти.
Раздел памяти для глобальных и статических данных, который инициализируется при объявлении. Поскольку начальное значение инициализируемых переменных известно заранее, все глобальные или статические переменные сохраняются вместе в исполняемый файл, а блок данных загружается в память непосредственно из исполняемого файла, как и текстовая часть.
Раздел bss, как и раздел данных, предназначен для хранения глобальных и статических переменных. Разница в том, что в разделе bss хранятся переменные, которые не были инициализированы определенным значением при объявлении. Данные Bss обнуляются при запуске программы.
В стеке хранятся различные значения указателей, которые необходимы для выполнения программы, а также это место хранения по умолчанию для переменных, которые являются локальными для функции, т. е. объявленными в теле функции.Данные стека создаются, когда программа запускает функцию, и уничтожаются при выходе из этой функции. Когда работающая функция вызывает другую функцию, данные новой функции помещаются перед данными исходной функции.
В дополнение к основной памяти компьютера также можно временно хранить несколько переменных непосредственно в ячейках памяти, называемых регистрами, которые являются частью ЦП компьютера.
5.5.1. Классы хранения¶
Каждое объявление переменной имеет 3 атрибута.
- тип (int, float, double, char, . ), обсуждаемый в теме 1.
- размещение объявления
- Глобальные переменные объявляются вне каких-либо функций, и по умолчанию к ним может обращаться любая функция в программе.
- Переменные, объявленные внутри функции (включая main()), доступны только той функции, в которой они определены. ол>
- авто — по умолчанию.
- внешний
- зарегистрироваться
- статический
- Это значение по умолчанию для переменных. Ключевое слово auto используется редко.
- Авто переменные помещаются в стек. Таким образом, как только функция, использующая переменную, завершает работу, переменная исчезает, и эта ячейка памяти становится доступной для использования другими функциями.
- При каждом вызове функции в стеке устанавливаются новые автоматические переменные. Функция знает только о своих собственных автоматических переменных и может получить доступ к автоматическим переменным других функций только с помощью указателей.
- Помимо основной памяти компьютера, ограниченный объем памяти имеется в самом ЦП. Компьютер может получить доступ к регистровой памяти намного быстрее, чем к основной памяти.
- Регистр ключевого слова – это рекомендуемый запрос на сохранение переменной в одном из регистров процессора.
- Рекомендация означает, что компилятор решил, будет ли удовлетворен этот запрос. Если вы запрашиваете большое количество переменных для хранения в регистрах, то компилятор не сможет выполнить ваш запрос. следует использовать экономно и только для переменных, к которым обращаются много раз в узком цикле. Лучше всего использовать регистровые переменные в небольших функциях, чтобы переменная использовалась в течение короткого промежутка времени.
5.5.1.1. авто¶
5.5.1.2. внешний¶
Когда переменная определена вне какой-либо функции (включая основную). Это глобальная переменная, которая размещается либо в секции данных, либо в секции bss памяти.
Любая функция в файле, где она объявлена, имеет доступ к глобальной переменной.
Использование ключевого слова extern в другом файле дает доступ к переменной во втором файле. Если объявление extern находится внутри функции, только эта функция имеет доступ к глобальной переменной. Если она находится вне какой-либо функции, то все функции в файле имеют доступ к переменной.
Оператор extern не объявляет переменную, а просто ссылается на глобальную переменную, которая была объявлена в другом файле.
5.5.1.3. зарегистрироваться¶
5.5.1.4. статический¶
Ключевое слово static используется двумя способами.
Статическая переменная, объявленная внутри функции, помещается в область данных или bss памяти и может сохранять свое значение между вызовами одной и той же функции. В этом смысле она похожа на глобальную переменную, за исключением того, что она используется только в одной функции. Ограничение на область действия статических переменных — это ограничение, реализованное компилятором; при этом программа на ассемблере может легко получить доступ к любым данным, хранящимся в разделах данных или bss памяти.
Статическая переменная, объявленная как глобальная, также называется статической внешней переменной. Здесь ключевое слово static дает результаты, противоположные ключевому слову extern. Переменная является глобальной для файла, в котором она объявлена, но на нее нельзя ссылаться в других файлах. Таким образом, ключевое слово static может привести к сокрытию данных.
Статические переменные предоставляют простые средства для сокрытия информации в программе на языке C. Другими словами, переменная может быть постоянной или глобальной, но мы можем не хотеть, чтобы другие программисты много знали об этой переменной — по крайней мере, они пытались ее изменить.
5.5.2. квалификатор const¶
Если при объявлении переменной используется ключевое слово const, мы ограничиваем изменение переменной после ее первоначального определения. const не является ключевым словом класса хранения, поскольку оно не влияет на область действия или расположение переменной в памяти.
Читайте также: