Программирование >>  Оптимизация возвращаемого значения 

1 2 3 [ 4 ] 5 6 7 ... 96


Глава 1. Основы

Указатели, ссылки, приведение типов, массивы, конструкторы - это то, что составляет основу языка. Все программы на языке С++, за исключением самых простых, используют большую часть названных понятий, а многие программы используют их все.

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

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

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

Правило 1. Различайте указатели и ссылки

Указатель (pointer) и ссылка (reference) существенно отличаются по внешнему виду (указатели используют операторы * (умножить) и -> (стрелка), ссылки используют оператор . (точка)), но применяются для решения одних и тех же задач. И указатели и ссылки позволяют неявно ссылаться на другие объекты. Как же тогда решить, когда применять указатели, а когда ссылки?

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

Но подождите! , - воскликнет читатель, - а как же будет работать следующий кусок кода? :



char *рс = О; / / Присвоить указателю значение null.

charSc rc = *рс; / / Установить ссылку на содержимое

нулевого указателя.

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

Так как ссылка должна ссылаться на объект, С++ требует ее инициализации:

str ing& г s; / / Ошибка! Ссылки должны быть

проинициализированы.

string S{ xyzzy );

string& rs = s; / / Нормально, rs ссылается на s .

Ha указатели таких ограничений не налагается:

string *ps; Неинициализированный указатель:

допустимо, но рискованно.

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

voidprintDouble(const double& rd) {

cout << rd; Нет необходимости пpoвepятьrd;

} она должна ссылаться на double.

Указатели же, наоборот, обычно должны проверяться на равенство нулю:

voidprintDouble (const double *pd) {

if (pd) { Проверка на значение null.

cout << *pd;

Другое важное различие между указателями и ссылками состоит в возможности присваивать зтсазателям различные значения для доступа к разным объектам. Ссылка же всегда указывает на один и тот же объект, заданный при ее инициализации:

string si( Nancy ) ; strings2( Clancy );

string& rs = si; rs ссылается на si.

string *ps = &sl; ps указывает на si.

rs = s2; rs все еще ссылается на si,

но теперь si имеет значение

Clancy .



ps = &s2; ps указывает на s2;

значение si не изменилось.

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

Существует еще одна ситуация, в которой вы должны задействовать ссылки -при реализации некоторых операторов; из них наиболее часто встречается оператор [ ] (скобки). Обычно этот оператор должен вернуть некое значение, которое затем будет использовано как принимающее в операторе присваивания:

vector<int>v{10) ; Создаем векторцелых значений

размерности 10;

векторявляетсяшаблоном

из стандартной библиотеки С++

(см.правило 35). v[5] =10; Значение,возвращаемое

оператором [],является

принимающей стороной оператора

присваивания.

Если бы оператор [ ] возвращал указатель, то последнюю строку этого кода надо было бы записать так:

*V[5] =10;

Но создавалось бы ложное впечатление, что v является вектором указателей. Поэтому почти всегда желательно, чтобы оператор [ ] возвращал ссылку. (Интересное исключение из этого правила приведено в правиле 30.)

Итак, использование ссылок оправдано, когда доподлинно известно, что объект ссылки существует, когда нет необходимости изменять значение ссылки и при реализации операторов, в которых применение указателей нежелательно из-за синтаксических требований. Во всех других случаях используйте указатели.

Правило 2. Предпочитайте приведение типов в стиле С++

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

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



1 2 3 [ 4 ] 5 6 7 ... 96

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика