Мегаобучалка Главная | О нас | Обратная связь


Активно используйте const



2016-01-26 352 Обсуждений (0)
Активно используйте const 0.00 из 5.00 0 оценок




 

 

Резюме

 

const — ваш друг: неизменяемые значения проще понимать, отслеживать и мотивировать, т.е. там, где это целесообразно, лучше использовать константы вместо переменных. Сделайте const описанием по умолчанию при определении значения — это безопасно, проверяемо во время компиляции (см. рекомендацию 14) и интегрируемо с системой типов С++. Не выполняйте преобразований типов с отбрасыванием const кроме как при вызове некорректной с точки зрения употребления const функции (см. рекомендацию 94).

 

Обсуждение

 

Константы упрощают код, поскольку вам достаточно только один раз взглянуть на ее определение, чтобы знать, чему она равна везде. Рассмотрим такой код:

void Fun(vector<int>& v) {

// ...

const size_t len = v.size();

// ... и еще 30 строк ...

}

Увидев такое определение len, вы получаете надежную информацию о семантике этой константы в пределах области ее видимости (в предположении, что код не устраняет ее константность, чего он делать не должен, как вы узнаете далее): это информация о длине v в определенной точке программы. Взглянув на одну строку, вы получили всю необходимую информацию для всей области видимости. Если бы переменная len не была определена как const, она могла бы быть позже изменена — непосредственно или косвенно.

Заметим, что описание const не является глубоким. Чтобы понять что имеется в виду, рассмотрим класс С, который имеет член типа X*. В объекте С, который является константой, член X* также является константой, но сам объект X, на который он указывает, константой не является (см. [Saks99]).

Логическую константность следует реализовывать с использованием членов, описанных как mutable. Когда константная функция-член класса оправданно требует модификации переменной-члена (т.е. когда эта переменная не влияет на наблюдаемое состояние объекта, например, если это кэшированные данные), объявите эту переменную-член как mutable. Заметим, что если все закрытые члены скрыты с использованием идиомы Pimpl (см. рекомендацию 43), описание mutable не является необходимым ни для кэшированной информации, ни для неизменного указателя на нее.

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

Корректное применение const дает отличные результаты и повышает эффективность. Чрезвычайно важно правильно и последовательно использовать модификатор const в ваших программах. Понимание того, как и где изменяется состояние программы, особенно необходимо, а модификатор const по сути документирует непосредственно в коде программы, где именно компилятор может помочь вам в этом. Правильное употребление const поможет вам лучше разобраться с вопросами проектирования и сделать ваш код более надежным и безопасным. Если вы выяснили, что некоторую функцию-член невозможно сделать константной, значит, вы более детально разобрались с тем, как, где и почему эта функция модифицирует состояние объекта. Кроме того, вы сможете понять, какие члены-данные объединяют физическую и логическую константность (см. приведенные ниже примеры).

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

 

Примеры

 

Пример. Избегайте const в объявлениях функций, принимающих параметры по значению. Два следующих объявления абсолютно эквивалентны:

void Fun(int x);

 

void Fun(const int x); // Объявление той же самой функции:

// const здесь игнорируется

Во втором объявлении модификатор const избыточен. Мы рекомендуем объявлять функции без таких высокоуровневых модификаторов const, чтобы тот, кто читает ваши заголовочные файлы, не был дезориентирован. Однако использование такого модификатора имеет значение в определении функции и его применение может быть оправдано с точки зрения обнаружения непреднамеренного изменения переданного параметра:

void Fun(const int x) { // определение функции Fun

// ...

++x; // Ошибка: нельзя изменять константное значение

// ...

}

 

Ссылки

 

[Allison98] §10 • [Cline99] §14.02-12 • [Dewhurst03] §6, §31-32, §82 • [Keffer95] pp. 5-6 • [Koenig97] §4 • [Lakos96] §9.1.6, §9.1.12 • [Meyers97] §21 • [Murray93] §2.7 • [Stroustrup00] §7.2, §10.2.6, §16.3.1 • [Sutter00] §43

 

Избегайте макросов

 

 

Резюме

 

Макрос — самый неприятный инструмент С и С++, оборотень, скрывающийся под личиной функции, кот, гуляющий сам по себе и не обращающий никакого внимания на границы ваших областей видимости. Берегитесь его!

 

Обсуждение

 

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

 

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

— [Sutter04] §31

 

 

Мне не нравится большинство видов препроцессоров и макросов. Одна из целей С++ — сделать препроцессор С излишним (§4.4, §18), поскольку я считаю его большой ошибкой

— [Stroustrup94] §3.3.1.

 

 

Макросы почти никогда не являются необходимыми в С++. Используйте const (§5.4) или enum (§4.8) для определения явных констант [см. рекомендацию 15] , inline (§7.1.1) для того, чтобы избежать накладных расходов на вызов функции [но см. рекомендацию 8], template (глава 13) для определения семейств функций и типов [см. рекомендации с 64 по 67] , и namespace (§8.2) для того, чтобы избежать конфликтов имен [см. рекомендации с 57 по 59].

— [Stroustrup00] §1.6.1

 

 

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

— [Stroustrup00] §7.8

 

Основная проблема с макросами С++ заключается в том, что они выглядят гораздо привлекательнее, чем являются таковыми на самом деле. Макросы игнорируют области видимости, игнорируют прочие возможности и правила языка, и заменяют все символы, которые переопределяют при помощи директивы #define, до самого конца файла. Применение макросов внешне походит на имя или вызов функции, но не имеет с ними ничего общего. Макросы "негигиеничны", в том смысле, что они могут быть раскрыты неожиданно, причем превратиться в зависимости от контекста их использования в самые разные конструкции. Подстановка текста, выполняемая макросами, делает написание хотя бы в небольшой степени "приличного" макроса смесью искусства и черной магии.

Программисты, которые полагают, что тяжелее всего расшифровать ошибки, связанные с шаблонами, вероятно, просто никогда не имели дела с плохо написанными или неверно использованными макросами. Шаблоны являются частью системы типов С++, и тем самым позволяют компилятору куда лучше справляться с ними, чем с макросами, которые имеют мало общего с языком программирования. Хуже того, в отличие от шаблонов неверные макросы могут быть раскрыты в нечто, что в силу чистой случайности скомпилируется, не имея при этом никакого смысла. И наконец, ошибка в макросе обнаруживается только после того, как макрос раскрывается, а не при его определении.

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

 

Примеры

 

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

macro(Foo<int, double>)

макрос воспринимает так, будто ему переданы два аргумента, а именно Foo<int и doublе>, в то время как в действительности эта конструкция представляет собой единый объект С++.

 

Исключения

 

Макросы остаются единственно возможным решением для некоторых важных задач, таких как защита директивы #include (см. рекомендацию 24), использование директив #ifdef и #if defined для условной компиляции и реализация assert (см. рекомендацию 68).

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

Можно (но осторожно) использовать макросы вместо большого количества копирований и вставок близких фрагментов кода.

Заметим, что [C99] и [Boost] включают соответственно умеренные и радикальные расширения препроцессоров.

 

Ссылки

 

[Boost] • [С99] • [Dewhurst03] §25-28 • [Lakos96] §2.3.4 • [Meyers96] §1 • [Stroustrup94] §3.3.1 • [Stroustrup00] §1.6.1, §7.8 • [Sutter02] §34-35 • [Sutter04] §31 • [Sutter04a]

 



2016-01-26 352 Обсуждений (0)
Активно используйте const 0.00 из 5.00 0 оценок









Обсуждение в статье: Активно используйте const

Обсуждений еще не было, будьте первым... ↓↓↓

Отправить сообщение

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



©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (352)

Почему 1285321 студент выбрали МегаОбучалку...

Система поиска информации

Мобильная версия сайта

Удобная навигация

Нет шокирующей рекламы



(0.012 сек.)