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

Отметим, что в этом примере в классе Lock больше нет деструктора. Просто в нем отпала необходимость. В правиле 5 объясняется, что деструктор класса (независимо от того, сгенерирован он компилятором или определен пользователем) автоматически вызывает деструкторы нестатических данных-членов класса. В нашем примере это mutexPtr. Но деструктор mutexPtr автоматически вызовет функцию-чистильщик tr1::shared_ptr (в данном случае unlock), когда счетчик ссылок на мьютекс достигнет нуля. (Пользователи, которые будут знакомиться с исходным текстом класса, вероятно, будут благодарны за комментарии, указывающие, что вы не забыли о деструкторе, а просто положились на поведение по умолчанию деструктора, сгенерированного компилятором.)

Копирование управляемого ресурса. Иногда допустимо иметь столько копий ресурса, сколько вам нужно, и единственная причина использования класса, управляющего ресурсами, – гарантировать, что каждая копия ресурса будет освобождена по окончании работы с ней. В этом случае копирование управляющего ресурсом объекта означает также копирование самого ресурса, который в него «обернут». То есть копирование управляющего ресурсом объекта выполняет «глубокое копирование». Некоторые реализации стандартного класса string включают указатели на память из «кучи», где хранятся символы, входящие в строку. Объект такого класса содержит указатель на память из «кучи». Когда объект string копируется, то копируется и указатель, и память, на которую он указывает. Здесь мы снова встречаемся с «глубоким копированием».

• Передача владения управляемым ресурсом. Иногда нужно гарантировать, что только один RAII-объект ссылается на ресурс, и при копировании такого объекта RAII владение ресурсом передается объекту-копии. Как объясняется в правиле 13, это означает копирование с применением auto_ptr.

Копирующие функции (конструктор копирования и оператор присваивания) могут быть сгенерированы компилятором, но если сгенерированные версии не делают того, что вам нужно (правило 5 объясняет поведение по умолчанию), придется написать их самостоятельно. Иногда имеет смысл поддерживать обобщенные версии этих функций. Такой подход описан в правиле 45.

Что следует помнить

• Копирование RAII-объектов влечет за собой копирование ресурсов, которыми они управляют, поэтому поведение ресурса при копировании определяет поведение RAII-объекта.

• Обычно при реализации RAII-классов применяется одна из двух схем: запрет копирования или подсчет ссылок, но возможны и другие варианты.

<p>Правило 15: Предоставляйте доступ к самим ресурсам из управляющих ими классов</p>

Управляющие ресурсами классы заслуживают всяческих похвал. Это бастион, защищающий от утечек ресурсов, а отсутствие таких утечек – фундаментальное свойство хорошо спроектированных систем. В идеальном мире вы можете положиться на эти классы для любых взаимодействий с ресурсами, не утруждая себя доступом к ним напрямую. Но мир неидеален. Многие программные интерфейсы требуют доступа к ресурсам без посредников. Если вы не планируете отказаться от использования таких интерфейсов (что редко имеет смысл на практике), то должны как-то обойти управляющий объект и работать с самим ресурсом.

Например, в правиле 13 изложена идея применения интеллектуальных указателей вроде auto_ptr или tr1::shared_ptr для хранения результата вызова фабричной функции createInvestment:

std::tr1::shared_ptr pInv(createInvestment()); // èç ïðàâèëà 13

Предположим, есть функция, которую вы хотите применить при работе с объектами класса Investment:

int daysHeld(const Investment *pi); // возвращает количество дней

// хранения инвестиций

Вы хотите вызывать ее так:

int days = daysHeld(pInv); // ошибка!

но этот код не скомпилируется: функция daysHeld ожидает получить указатель на объект класса Investment, а вы передаете ей объект типа tr1::shared_ptr .

Необходимо как-то преобразовать объект RAII-класса (в данном случае tr1::shared_ptr) к типу управляемого им ресурса (то есть Investment*). Есть два основных способа сделать это: неявное и явное преобразование.

И tr1::shared_ptr, и auto_ptr предоставляют функцию-член get для выполнения явного преобразования, то есть возврата (копии) указателя на управляемый объект:

int days = daysHeld(pInv.get()); // нормально, указатель, хранящийся

// в pInv, передается daysHeld

Как почти все классы интеллектуальных указателей, tr1::shared_ptr и auto_ptr перегружают операторы разыменования указателей (operator-> и operator*), и это обеспечивает возможность неявного преобразования к типу управляемого указателя:

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

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

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

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

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

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

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

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

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