Выбрать главу

При выполнении этой программы вы убедитесь, что цикл с "регистровым" управлением выполняется приблизительно в два раза быстрее, чем цикл с "нерегистровым" управлением. Если вы не увидели ожидаемой разницы, это может означать, что ваш компилятор оптимизирует все переменные. Просто "поиграйте" программой до тех пор, пока разница не станет очевидной.

На заметку. При написании этой книги была использована среда Visual C++, которая игнорирует ключевое слово register. Visual C++ применяет оптимизацию "как считает нужным". Поэтому вы можете не заметить влияния спецификатора register на выполнение предыдущей программы. Однако ключевое слово register все еще принимается компилятором без сообщения об ошибке. Оно просто не оказывает никакого воздействия.

Перечисления 

В C++ можно определить список именованных целочисленных констант. Такой список называется перечислением (enumeration). Эти константы можно затем использовать везде, где допустимы целочисленные значения (например, в целочисленных выражениях). Перечисления определяются с помощью ключевого слова enum, а формат их определения имеет такой вид:

enum type_name { список_перечисления } список_переменных;

Под элементом список_перечисления понимается список разделенных запятыми имен, которые представляют значения перечисления. Элемент список_переменных необязателен, поскольку переменные можно объявить позже, используя имя типа перечисления. В следующем примере определяется перечисление apple и две переменные типа apple с именами red и yellow.

enum apple {Jonathan, Golden_Del, Red_Del, Winesap, Cortland, McIntosh} red, yellow;

Определив перечисление, можно объявить другие переменные этого типа, используя имя перечисления. Например, с помощью следующей инструкции объявляется одна переменная fruit перечисления apple.

apple fruit;

Эту инструкцию можно записать и так.

enum apple fruit;

Ключевое слово enum объявляет перечисление.

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

С учетом предыдущих объявлений следующие типы инструкций совершенно допустимы.

fruit = Winesap;

if(fruit==Red_Del) cout << "Red Delicious\n";

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

cout << Jonathan << ' ' << Cortland;

на экран будут выведены числа 0 4.

Несмотря на то что перечислимые константы автоматически преобразуются в целочисленные, обратное преобразование автоматически не выполняется. Например, следующая инструкция некорректна.

fruit =1; // ошибка

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

fruit = (apple) 1; // Теперь все в порядке, но стиль не совершенен.

Теперь переменная fruit будет содержать значение Golden_Del, поскольку эта apple-константа связывается со значением 1. Как отмечено в комментарии, несмотря на то, что эта инструкция стала корректной, ее стиль оставляет желать лучшего, что простительно лишь в особых обстоятельствах.

Используя инициализатор, можно указать значение одной или нескольких перечислимых констант. Это делается так: после соответствующего элемента списка перечисления ставится знак равенства и нужное целое число. При использовании инициализатора следующему (после инициализированного) элементу списка присваивается значение, на единицу превышающее предыдущее значение инициализатора. Например, при выполнении следующей инструкции константе Winesap присваивается значение 10.

enum apple {Jonathan, Golden_Del, Red_Del, Winesap=10, Cortland, McIntosh};

Часто в отношении перечислений ошибочно предполагается, что символы перечисления можно вводить и выводить как строки. Например, следующий фрагмент кода выполнен не будет.