Глава 9: Еще о типах данных и операторах



 

Прежде чем переходить к более сложным средствам C++, имеет смысл подробнее познакомиться с некоторыми типами данных и операторами. Кроме уже рассмотренных нами типов данных, в C++ определены и другие. Одни из них состоят из модификаторов, добавляемых к уже известным вам типам. Другие включают перечисления, а третьи используют ключевое слово typedef . C++ также поддерживает ряд операторов, которые значительно расширяют область действия языка и позволяют решать задачи программирования в весьма широком диапазоне. Речь идет о поразрядных операторах, операторах сдвига, а также операторах "?" и sizeof . Кроме того, в этой главе рассматриваются такие специальные операторы, как new и delete . Они предназначены для поддержки С++‑системы динамического распределения памяти.

 

Спецификаторы типа const и volatile

 

Спецификаторы типа const и volatile управляют доступом к переменной.

В C++ определено два спецификатора типа, которые оказывают влияние на то, каким образом можно получить доступ к переменным или модифицировать их. Это спецификаторы const и volatile . Официально они именуются cv‑спецификаторами и должны предшествовать базовому типу при объявлении переменной.

 

Спецификатор типа const

 

Переменные, объявленные с использованием спецификатора const , не могут изменить свои значения во время выполнения программы. Однако любой const ‑переменной можно присвоить некоторое начальное значение. Например, при выполнении инструкции

 

 

создается double ‑переменная version , которая содержит значение 3.2 , и это значение программа изменить уже не может. Но эту переменную можно использовать в других выражениях. Любая const ‑переменная получает значение либо во время явно задаваемой инициализации, либо при использовании аппаратно‑зависимых средств. Применение спецификатора const к объявлению переменной гарантирует, что она не будет модифицирована другими частями вашей программы.

Спецификатор const предотвращает модификацию переменной при выполнении программы.

Спецификатор const имеет ряд важных применений. Возможно, чаще всего его используют для создания const ‑параметров типа указатель. Такой параметр‑указатель защищает объект, на который он ссылается, от модификации со стороны функции. Другими словами, если параметр‑указатель предваряется ключевым словом const , никакая инструкция этой функции не может модифицировать переменную, адресуемую этим параметром. Например, функция code() в следующей короткой программе сдвигает каждую букву в сообщении на одну алфавитную позицию (т.е. вместо буквы 'А' ставится буква 'Б' и т.д.), отображая таким образом сообщение в закодированном виде. Использование спецификатора const в объявлении параметра не позволяет коду функции модифицировать объект, на который указывает этот параметр.

 

 

Поскольку параметр str объявляется как const ‑указатель, у функции code() нет никакой возможности внести изменения в строку, адресуемую параметром str . Но если вы попытаетесь написать функцию code() так, как показано в следующем примере, то обязательно получите сообщение об ошибке, и программа не скомпилируется.

 

 

Поскольку параметр str является const ‑указателем, его нельзя использовать для модификации объекта, на который он ссылается.

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

 

 

Спецификатор const еще можно использовать для подтверждения того, что ваша программа не изменяет значения некоторой переменной. Вспомните, что переменная типа const может быть модифицирована внешними устройствами, т.е. ее значение может быть установлено каким‑нибудь аппаратным устройством (например, датчиком). Объявив переменную с помощью спецификатора const , можно доказать, что любые изменения, которым подвергается эта переменная, вызваны исключительно внешними событиями.

Наконец, спецификатор const используется для создания именованных констант. Часто в программах многократно применяется одно и то же значение для различных целей. Например, необходимо объявить несколько различных массивов таким образом, чтобы все они имели одинаковый размер. Когда нужно использовать подобное "магическое число", имеет смысл реализовать его в виде const ‑переменной. Затем вместо реального значения можно использовать имя этой переменной, а если это значение придется впоследствии изменить, вы измените его только в одном месте программы. Следующая программа позволяет попробовать этот вид применения спецификатора const "на вкус".

 

 

Если в этом примере понадобится использовать новый размер для массивов, вам потребуется изменить только объявление переменной size и перекомпилировать программу. В результате все три массива автоматически получат новый размер.

 

Спецификатор типа volatile

 

Спецификатор volatile информирует компилятор о том, что данная переменная может быть изменена внешними (по отношению к программе) факторами.

Спецификатор volatile сообщает компилятору о том, что значение соответствующей переменной может быть изменено в программе неявным образом. Например, адрес некоторой глобальной переменной может передаваться управляемой прерываниями подпрограмме тактирования, которая обновляет эту переменную с приходом каждого импульса сигнала времени. В такой ситуации содержимое переменной изменяется без использования явно заданных инструкций программы. Существуют веские основания для того, чтобы сообщить компилятору о внешних факторах изменения переменной. Дело в том, что С++‑компилятору разрешается автоматически оптимизировать определенные выражения в предположении, что содержимое той или иной переменной остается неизменным, если оно не находится в левой части инструкции присваивания. Но если некоторые факторы (внешние по отношению к программе) изменят значение этого поля, такое предположение окажется неверным, в результате чего могут возникнуть проблемы.

Например, в следующем фрагменте программы предположим, что переменная clock обновляется каждую миллисекунду часовым механизмом компьютера. Но, поскольку переменная clock не объявлена с использованием спецификатора volatile , этот фрагмент кода может иногда работать недолжным образом. (Обратите особое внимание на строки, обозначенные буквами "А" и "Б" .)

 

 

В этом фрагменте переменная clock получает свое значение, когда она присваивается переменной timer в строке А. Но, поскольку переменная clock не объявлена с использованием спецификатора volatile , компилятор волен оптимизировать этот код, причем таким способом, при котором значение переменной clock , возможно, не будет опрошено в инструкции cout (строка Б), если между строками А и Б не будет ни одного промежуточного присваивания значения переменной clock . (Другими словами, в строке Б компилятор может просто еще раз использовать значение, которое получила переменная clock в строке А .) Но если между моментами выполнения строк А и Б поступят очередные импульсы сигнала времени, то значение переменной clock обязательно изменится, а строка Б в этом случае не отразит корректный результат.

Для решения этой проблемы необходимо объявить переменную clock с ключевым словом volatile .

 

 

Теперь значение переменной clock будет опрашиваться при каждом ее использовании.

И хотя на первый взгляд это может показаться странным, спецификаторы const и volatile можно использовать вместе. Например, следующее объявление абсолютно допустимо. Оно создает const ‑указатель на volatile ‑объект.

 

 

В этом примере для преобразования целочисленного литерала 0x2112 в const ‑указатель на volatile ‑символ необходимо применить операцию приведения типов.

 

Спецификаторы классов памяти

 

C++ поддерживает пять спецификаторов классов памяти:

 

 

Спецификаторы классов памяти определяют, как должна храниться переменная.

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

Спецификатор mutable применяется только к объектам классов, о которых речь впереди. Остальные спецификаторы мы рассмотрим в этом разделе.

 


Дата добавления: 2018-09-22; просмотров: 277; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!