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

lvalue есть выражение, ссылающееся на объект" (#с.5). Слово «lvalue» первоначально было придумано для значения «нечто, что может стоять в левой части присваивания». Однако не всякое lvalue можно использовать в левой части присваивания; бывают lvalue, ссылающиеся на константу (см. #2.4).

2.1.3 Время жизни

Если программист не указал иного, то объект создается, когда встречается его описание, и уничтожается, когда его имя выходит из области видимости, Объекты с глобальными именами создаются и инициализируются один раз (только) и «живут» до завершения программы. Объекты, определенные описанием с ключевым словом static, ведут себя так же. Например*:

– * Команда #include «stream.h» была выброшена из примеров в этой главе для экономии места. Она необходима в примерах, производящих вывод, чтобы они были полными. (прим. автора)

int a = 1;

void f() (* int b = 1; // инициализируется при каждом // вызове f() static int c = 1; // инициализируется только один раз cout «„ " a = " «« a++ «« " b = " «« b++ «« " c = " «« c++ «« «\n“; *)

main() (* while (a « 4) f(); *)

производит вывод

a = 1 b = 1 c = 1 a = 2 b = 1 c = 2 a = 3 b = 1 c = 3

Не инициализированная явно статическая (static) переменная неявно инициализируется нулем.

С помощью операций new и delete программист может также создавать объекты, время жизни которых управляется непосредственно, см. #3.2.4.

2.2 Имена

Имя (идентификатор) состоит из последовательности букв и цифр. Первый символ должен быть буквой. Символ подчерка _ считается буквой. С++ не налагает ограничений на число символов в имени, но некоторые части реализации находятся вне ведения автора компилятора (в частности, загрузчик), и они, к сожалению, такие ограничения налагают. Некоторые среды выполнения также делают необходимым расширить или ограничить набор символов, допустимых в идентификаторе. Расширения (например, при допущении в именах символа $) порождают непереносимые программы. В качестве имени не могут использоваться ключевые слова С++ (см. #с.2.3). Примеры имен:

hello this_is_a_most_unusially_long_name DEFINED foO bAr u_name HorseSense var0 var1 CLASS _class ___

Примеры последовательностей символов, которые не могут использоваться как идентификаторы:

012 a fool $sys class 3var pay.due foo~bar .name if

Буквы в верхнем и нижнем регистрах считаются различными, поэтому Count и count – различные имена, но вводить имена, лишь незначительно отличающиеся друг от друга, нежелательно. Имена, начинающиеся с подчерка, по традиции используются для специальных средств среды выполнения, поэтому использовать такие имена в прикладных программах нежелательно.

Во время чтения программы компилятор всегда ищет наиболее длинную строку, составляющую имя, поэтому var10 – это оно имя, а не имя var, за которым следует число 10, и elseif – одно имя, а не ключевое слово else, после которого стоит ключевое слово if.

2.3 Типы

Каждое имя (идентификатор) в С++ программе имеет ассоциированный с ним тип. Этот тип определяет, какие операции моно применять к имени (то есть к объекту, на который оно ссылается), и как эти операции интерпретируются. Например:

int error number; float real(complex* p);

Поскольку error_number описано как int, его можно присваивать, использовать в арифметических выражениях и т.д. Тогда как функция real может вызываться с адресом complex в качестве параметра. Можно взять адрес любого из них. Некоторые имена, вроде int и complex, являются именами типов. Обычно имя типа используется в описании для спецификации другого имени. Единственные отличные от этого действия над именем типа – это sizeof (для определения количества памяти, которая требуется для хранения объекта типа) и new (для размещения объекта типа в свободной памяти). Например:

main() (* int* p = new int; cout «„ "sizeof(int) = " «« sizeof(int) «\n“; *)

Имя типа можно также использовать для задания явного преобразования одного типа в другой, например:

float f; char* p; //... long ll = long(p); // преобразует p в long int i = int(f); // преобразует f в int

2.3.1 Основные типы

В С++ есть набор основных типов, которые соответствуют наиболее общим основным единицам памяти компьютера и наиболее общим основным способам их использования:

char short int int long int

для представления целых различных размеров,

float double

для представления чисел с плавающей точкой,

unsigned char unsigned short int unsigned int unsigned long int

для представления беззнаковых целых, логических значений, битовых массивов и т.п. Для большей компактности записи можно опускать int в комбинациях из нескольких слов, что не меняет смысла. Так, long означает long int, и unsigned тип означает тип unsigned int. В общем, когда в описании опущен тип, он предполагается int. Например:

const a = 1; static x;

все определяют объект типа int.

Целый тип char наиболее удобен для хранения и обработки символов на данном компьютере, обычно это 8-битовый байт. Размеры объектов С++ выражаются в единицах размера char, потому по определению sizeof(char)==1. В зависимости от аппаратного обеспечения char является знаковым или беззнаковым целым. Тип unsigned char, конечно, всегда беззнаковый, и при его использовании получаются более переносимые программы, но из-за применения его вместо просто char могут возникать значительные потери в эффективности.

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

1==sizeof(char)«=sizeof(short)«= sizeof(int)«=sizeof(long) sizeof(float)«=sizeof(double)

Однако обычно разумно предполагать, что в char могут храниться целые числа в диапазоне 0..127 (в нем всегда могут храниться символы машинного набора символов), что short и int имеют не менее 16 бит, что int имеет размер, соответствующий целой арифметике, и что long имеет по меньшей мере 24 бита. Предполагать что-либо помимо этого рискованно, и даже эти эмпирические правила применимы не везде. Таблицу характеристик аппаратного обеспечения для некоторых машин можно найти в #с. 2.6.

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

unsigned surprise = -1;

допустимо (но компилятор обязательно сделает предупреждение).

2.3.2 Неявное преобразование типа

Основные типы можно свободно сочетать в присваиваниях и выражениях. Везде, где это возможно, значения преобразуются так, чтобы информация не терялась. Точные правила можно найти в #с.6.6.