Читаем Стандарты программирования на С++ полностью

Никогда не забывайте о времени жизни объекта и его корректности. Не разыменовывайте недействительные итераторы и указатели. Не делайте никаких предположений о том, что делает и чего не делает оператор delete; освобожденная память — это освобожденная память, и обращений к ней не должно быть ни при каких условиях. Не пытайтесь играться со временем жизни объекта путем вызова деструктора вручную (например, obj.~T()) с последующим вызовом размещающего new (см. рекомендацию 55).

Не используйте небезопасное наследство С: strcpy, strncpy, sprintf или прочие функции, которые выполняют запись в буфер без проверки выхода за его пределы. Функция strcpy не выполняет проверки границ буфера, а функция [C99] strncpy выполняет проверку, но не добавляет нулевой символ при выходе на границу. Обе эти функции — потенциальный источник неприятностей. Используйте современные, более безопасные и гибкие структуры и функции, такие, которые имеются в стандартной библиотеке С++ (см. рекомендацию 77). Они не всегда совершенно безопасны (в основном это связано с вопросами эффективности), но существенно меньше подвержены ошибкам и позволяют создавать гораздо более безопасный код.

Ссылки

[C99] • [Sutter00] §1 • [Sutter04] §2-3

<p>100. Не рассматривайте массивы полиморфно</p>Резюме

Полиморфная работа с массивами — большая ошибка. К сожалению, обычно компилятор никак на нее не реагирует. Не попадайтесь в эту ловушку!

Обсуждение

Указатели служат одновременно для двух целей: в качестве малого размера идентификаторов объектов и в качестве итераторов для массивов (они могут обходить массивы объектов с использованием арифметики указателей). В качестве идентификаторов имеет смысл рассматривать указатель на Derived как указатель на Base. Однако как только мы переходим ко второй цели, такая замена не работает, поскольку массив объектов Derived — совсем не то же, что и массив объектов Base. Чтобы проиллюстрировать сказанное, заметим, что и мышь, и слон — оба млекопитающие, но это не значит, что колонна из ста слонов будет по длине такой же, что и колонна из ста мышей.

Размер имеет значение. При замене указателя на Derived указателем на Base компилятор точно знает, как следует подкорректировать (при необходимости) указатель, поскольку у него есть достаточное количество информации об обоих классах. Однако при выполнении арифметических операций над указателем p на Base компилятор вычисляет p[n] как *(p+n*sizeof(Base)), таким образом полагаясь на то, что объекты, находящиеся в памяти, — это объекты типа Base, а не некоторого производного типа, который может иметь другой размер. Представляете, какая ерунда может получиться при работе с массивом объектов Derived, если вы преобразуете указатель на начало этого массива в указатель типа Base* (что компилятор вполне допускает), а затем примените арифметические операции к этому указателю (что компилятор также пропустит, не моргнув глазом)!

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

Для хранения массива полиморфных объектов вам нужен массив (а еще лучше — контейнер; см. рекомендацию 77) указателей на базовый класс (например, обычных указателей или, что еще лучше, интеллектуальных указателей shared_ptr; см. рекомендацию 79). Тогда каждый указатель массива указывает на полиморфный объект, скорее всего, объект в динамически выделенной памяти. (Если вы хотите обеспечить интерфейс контейнера полиморфных объектов, вам надо инкапсулировать весь массив и предоставить соответствующий полиморфный интерфейс для выполнения итераций.)

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

Ссылки

[C++TR104] • [Dewhurst03] §33, §89 • [Sutter00] §36 • [Meyers96] §3

<p>Список литературы</p>

Примечание: для удобства читателей весь список литературы доступен по адресу http://www.gotw.ca/publications/c++cs/bibliography.htm

Ссылки, выделенные полужирным шрифтом (например, [Abrahams96]), представляют собой гиперссылки в приведенной выше странице.

[Abelson96] Abelson H. and Sussman G. J. Structure and Interpretation of Computer Programs (2nd Edition) (MIT Press, 1996).

[Abrahams96] Abrahams D. Exception Safety in STLport. STLport website, 1996.

Перейти на страницу:

Все книги серии C++ In-Depth

Стандарты программирования на С++
Стандарты программирования на С++

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

Андрей Александреску , Герб Саттер

Программирование, программы, базы данных

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных