Шрифт:
(* cerr «„ «операция new не прошла: за пределами памяти\n“; exit(1); *)
typedef void (*PF); // тип указатель на функцию
extern PF set_new_handler(PF);
main (* set_new_handler(out_of_store); char* p = new char[100000000]; cout «„ "сделано, p = " «« long(p) «« «\n“; *)
как правило, не будет писать «сделано», а будет вместо этого выдавать
операция new не прошла: за пределами памяти
Функция _new_handler может делать и кое-что поумней, чем просто завершать выполнение программы. Если вы знаете, как работают new и delete, например, потому, что вы задали свои собственные operator new и operator delete, программа оработки может попытаться найти некоторое количество памяти, которое возвратит new. Другими словами, пользователь может сделать сборщик мусора, сделав, таким образом, использование delete необязательным. Но это, конечно, все-таки задача не для начинающего.
По историческим причинам new просто возвращает указатель 0, если она не может найти достаточное количество памяти и не был задан никакой _new_handler. Например
include «stream.h»
main (* char* p = new char[100000000]; cout «„ "сделано, p = " «« long(p) «« «\n“; *)
выдаст
сделано, p = 0
Вам сделали предупреждение! Заметьте, что тот, кто задет _new_handler, берет на себя заботу по проверке истощения памяти при каждом использовании new в программе (за исключнием случая, когда пользователь задал отдельные подпрограммы для размещения объектов заданных типов, определяемых пользвателем, см. #5.5.6).
3.3 Сводка операторов
Операторы С++ систематически и полностью изложены в #с.9, прочитайте, пожалуйста, этот раздел. А здесь приводится краткая сводка и некоторые примеры.
Синтаксис оператора – оператор: описание (*список_операторов opt*) выражение opt
if оператор if ( выражение ) оператор if ( выражение ) оператор else оператор switch оператор switch ( выражение ) оператор
while ( выражение ) оператор do оператор while (выражение) for ( оператор выражение opt; выражение opt ) оператор
case константное_выражение : оператор default : оператор break ; continue ;
return выражение opt ;
goto идентификатор ; идентификатор : оператор
список_операторов: оператор оператор список_операторов
Заметьте, что описание является оператором, и что нет операторов присваивания и вызова процедуры. Присваивание и вызов функции обрабатываются как выражения.
3.3.1 Проверки
Проверка значения может осуществляться или оператором if, или оператором switch:
if ( выражение ) оператор if ( выражение ) оператор else оператор switch ( выражение ) оператор
В С++ нет отдельного булевского типа. Операции сравнения
== != « „= “ »=
возвращают целое 1, если сравнение истинно, иначе возращают 0. Не так уж непривычно видеть, что ИСТИНА определена как 1, а ЛОЖЬ определена как 0.
В операторе if первый (или единственный) оператор выпоняется в том случае, если выражение ненулевое, иначе выполнется второй оператор (если он задан). Отсюда следует, что в качестве условия может использоваться любое целое выражение. В частности, если a целое, то
if (a) // ...
эквивалентно
if (a != 0) // ...
Логические операции amp; amp; !! ! наиболее часто используются в условиях. Операции amp; amp; и !! не будут вычислять второй аргмент, если это ненужно. Например:
if (p amp; amp; 1«p-»count) // ...
вначале проверяет, является ли p не нулем, и только если это так, то проверяет 1«p-»count.
Некоторые простые операторы if могут быть с удобством
заменены выражениями арифметического if. Например:
if (a «= d) max = b; else max = a;
лучше выражается так:
max = (a«=b) ? b : a;
Скобки вокруг условия необязательны, но я считаю, что когда они используются, программу легче читать.
Некоторые простые операторы switch можно по-другому зписать в виде набора операторов if. Например:
switch (val) (* case 1: f; break; case 2; g; break; default: h; break; *)
иначе можно было бы записать так:
if (val == 1) f; else if (val == 2) g; else h;
Смысл тот же, однако первый вариант (switch) предпочттельнее, поскольку в этом случае явно выражается сущность действия (сопоставление значения с рядом констант). Поэтому в нетривиальных случаях оператор switch читается легче.
Заботьтесь о том, что switch должен как-то завершаться, если только вы не хотите, чтобы выполнялся следующий case. Например:
switch (val) (* // осторожно case 1: cout «„ „case 1\n“; case 2; cout „« «case 2\n“; default: cout «« «default: case не найден\n“; *)
при val==1 напечатает
case 1 case 2 default: case не найден
к великому изумлению непосвященного. Самый обычный спсоб завершить случай – это break, иногда можно даже использвать goto. Например:
switch (val) (* // осторожно