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

(e) pc = 0; (i) pc = '0';

(f) st = pc; (j) st = ival;

(g) ch = pc[0]; (k) ch = *pc;

(h) pc = st; (l) *pc = ival;

Упражнение 3.13

Объясните разницу в поведении следующих операторов цикла:

while ( st++ )

++cnt;

while ( *st++ )

++cnt;

Упражнение 3.14

Даны две семантически эквивалентные программы. Первая использует встроенный строковый тип, вторая – класс string:

// ***** Реализация с использованием C-строк *****

#include iostream

#include cstring

int main()

{

int errors = 0;

const char *pc = "a very long literal string";

for ( int ix = 0; ix 1000000; ++ix )

{

int len = strlen( pc );

char *pc2 = new char[ len + 1 ];

strcpy( pc2, pc );

if ( strcmp( pc2, pc ))

++errors;

delete [] pc2;

}

cout "C-строки: "

errors " ошибок.\n";

}

// ***** Реализация с использованием класса string *****

#include iostream

#include string

int main()

{

int errors = 0;

string str( "a very long literal string" );

for ( int ix = 0; ix 1000000; ++ix )

{

int len = str.size();

string str2 = str;

if ( str != str2 )

}

cout "класс string: "

errors " ошибок.\n;

}

Что эти программы делают?

Оказывается, вторая реализация выполняется в два раза быстрее первой. Ожидали ли вы такого результата? Как вы его объясните?

Упражнение 3.15

Могли бы вы что-нибудь улучшить или дополнить в наборе операций класса string, приведенных в последнем разделе? Поясните свои предложения

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

Возьмем следующий пример кода:

for ( int index = 0; index 512; ++index )

... ;

С использованием литерала 512 связаны две проблемы. Первая состоит в легкости восприятия текста программы. Почему верхняя граница переменной цикла должна быть равна именно 512? Что скрывается за этой величиной? Она кажется случайной...

Вторая проблема касается простоты модификации и сопровождения кода. Предположим, программа состоит из 10 000 строк, и литерал 512 встречается в 4% из них. Допустим, в 80% случаев число 512 должно быть изменено на 1024. Способны ли вы представить трудоемкость такой работы и количество ошибок, которые можно сделать, исправив не то значение?

Обе эти проблемы решаются одновременно: нужно создать объект со значением 512. Присвоив ему осмысленное имя, например bufSize, мы сделаем программу гораздо более понятной: ясно, с чем именно сравнивается переменная цикла.

index bufSize

В этом случае изменение размера bufSize не требует просмотра 400 строк кода для модификации 320 из них. Насколько уменьшается вероятность ошибок ценой добавления всего одного объекта! Теперь значение 512 локализовано.

int bufSize = 512; // размер буфера ввода

// ...

for ( int index = 0; index bufSize; ++index )

// ...

Остается одна маленькая проблема: переменная bufSize здесь является l-значением, которое можно случайно изменить в программе, что приведет к трудно отлавливаемой ошибке. Вот одна из распространенных ошибок – использование операции присваивания (=) вместо сравнения (==):

// случайное изменение значения bufSize

if ( bufSize = 1 )

// ...

В результате выполнения этого кода значение bufSize станет равным 1, что может привести к совершенно непредсказуемому поведению программы. Ошибки такого рода обычно очень тяжело обнаружить, поскольку они попросту не видны.

Использование спецификатора const решает данную проблему. Объявив объект как

const int bufSize = 512; // размер буфера ввода

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

// ошибка: попытка присваивания значения константе

if ( bufSize = 0 ) ...

Раз константе нельзя присвоить значение, она должна быть инициализирована в месте своего определения. Определение константы без ее инициализации также вызывает ошибку компиляции:

const double pi; // ошибка: неинициализированная константа

Давайте рассуждать дальше. Явная трансформация значения константы пресекается компилятором. Но как быть с косвенной адресацией? Можно ли присвоить адрес константы некоторому указателю?

const double minWage = 9.60;

// правильно? ошибка?