Читаем Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ полностью

Ресурс – это нечто такое, что после использования должно быть возвращено системе. Если этого не сделать, случаются неприятности. В программах на C++ наиболее часто используемым ресурсом является динамическая память (если вы выделяете память и никогда ее не освобождаете, то получаете утечку памяти), но это лишь один из множества ресурсов, которыми нужно управлять. К другим часто используемым ресурсам относятся файловые дескрипторы, мьютексы, шрифты и кисти в графических интерфейсах пользователя (GUI), соединения с базой данных и сетевые сокеты. Независимо от вида ресурсов, важно, чтобы по окончании использования они были освобождены.

Попытки обеспечить это «вручную» представляют сложность при любых условиях, но если принять во внимание исключения, функции со многими путями возврата и приложения, модифицируемое программистами без отчетливого понимания последствий вносимых изменений, то становится ясно, что придумывать в каждом случае особый способ управления ресурсами нежелательно.

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

<p>Правило 13: Используйте объекты для управления ресурсами</p>

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

class Investment {...} // корневой класс иерархии

// типов инвестиций

Предположим далее, что библиотека предоставляет объекты, описывающие конкретные инвестиции, с помощью фабричной функции (см. правило 7):

Investment *createInvestment(); // возвращает указатель на динамически

// распределенный объект в иерархии

// Investment: вызвавший клиент обязан

// удалить его (параметры для простоты

// опущены)

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

void f()

{

Investment *pInv = createInvestment(); // вызвать фабричную функцию

... // использовать pInv

delete pInv; // освободить память, занятую

} // объектом

Выглядит хорошо, но есть несколько случаев, когда f не удастся удалить объект инвестиций, полученный от createlnvestment. Где-нибудь внутри непоказанной части функции может встретиться предложение return. Если такой возврат будет выполнен, то управление никогда не достигнет оператора delete. Похожая ситуация может случиться, если вызов createlnvestment и delete поместить в в цикл, и этот цикл будет прерван в результате выполнения goto или continue. И наконец, некоторые предложения внутри части, обозначенной «…», могут возбудить исключение. И в этом случае управление не дойдет до оператора delete. Независимо от того, почему delete будет пропущен, мы потеряем не только память, выделенную для объекта Investment, но и все ресурсы, которые он захватил.

Конечно, тщательное программирование может предотвратить ошибки подобного рода, но подумайте о том, как может измениться код со временем. При сопровождении программы кто-то может добавить предложение return или continue, не вполне понимая последствий своих действий для стратегии управления ресурсами, реализованной в данной функции. Хуже того, часть «…» функции f может вызвать функцию, которая никогда не возбуждала исключений, но начнет это делать после некоторого «усовершенствования». То есть полагаться на то, что f всегда доберется до своего оператора delete, просто нельзя.

Чтобы обеспечить освобождение ресурса, возвращенного createlnvestment, нам нужно инкапсулировать ресурс внутри объекта, чей деструктор автоматически освободит его, когда управление покинет функцию f. Фактически это половина идеи дела: заключая ресурс в объект, мы можем положиться на автоматический вызов деструкторов C++, чтобы гарантировать их освобождение. (Вторую половину мы обсудим чуть ниже.)

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

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

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

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

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

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

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

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

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