|
Программирование >> Оптимизация возвращаемого значения
нет переносимого способа определить обратное, поэтому все попытки обречены на неудачу. Это неудивительно. В конце концов, если бы можно было определить, что адрес находится в Kje, был бы способ определить, что его там нет. Но нельзя сделать ни того, ни, соответственно, другого. Правило 28. Используйте интеллектуальные указатели Интеллектуальные указатели (smart pointers) являются объектами, которые разработаны так, чтобы выглядеть и действовать как встроенные указатели, обеспечивая при этом большую функциональность. Они находят множество применений, включая управление ресурсами (см. правила 9, 10, 25 и 31) и автоматизацию программирования повторяющихся задач (см. правила 17 и 29). Если вы используете интеллектуальные указатели вместо встроенных указателей языка С++ (то есть неинтеллектуальных, или обычных указателей (dumb pointers)), вы можете управлять следующими аспектами поведения указателей: □ созданием и уничтожением. Вы определяете, что происходит при создании и уничтожении интеллектуального указателя. Обычно интеллектуальным указателям по умолчанию присваивается значение О, чтобы не допустить ошибок, возникающих из-за неинициализированных указателей. Некоторые интеллектуальные указатели отвечают за удаление объекта после того, как будет уничтожен последний указывающий на объект интеллектуальный указатель. Это косвенно позволяет избежать утечек памяти; □ копирование и присваивание. Вы управляете тем, что происходит при копировании или присвоении интеллектуального указателя. Для некоторых типов интеллектуальных указателей нужно, чтобы он автоматически копировал или присваивал то, на что указывает, то есть выполнял бы детальную копию (deep сору). Для других должен копироваться или присваиваться только сам указатель. Для третьих эти операции следует запретить. Но независимо от поведения разных типов интеллектуальных указателей их грамотное использование позволяет добиться нужного функционирования программы; □ разыменование (dereferencing). Что должно произойти, если клиент обращается к объекту, на который ссылается интеллектуальный указатель? Это решаете вы. Например, вы можете использовать интеллектуальные указатели, чтобы реализовать стратегию отложенной выборки, описанную в правиле 17. Интеллектуальные указатели создаются на основе шаблонов, поскольку так же, как и встроенные указатели, они должны быть максимально типизированы; параметр шаблона определяет тип объекта, на который он указывает. Большинство шаблонов интеллектуальных указателей выглядят примерно так: template<class Т> Шаблон для объектов class SmartPtr { интеллектуальных public: указателей. SmartPtr (Т* realPtr = 0) ; Создать интеллектуальный указатель на объект на основе простого указателя; неинициализированным указателям присваивается значение О (null). SmartPtr(const SmartPtr& rhs); Скопировать интеллектуальныйуказатель. -SmartPtrО; Уничтожить интеллектуальный указатель. Присвоить интеллектуальный указатель. SmartPtrSc operator= (const SmartPtrSc rhs) ; T* operator->() const; Разыменовать интеллектуальный указатель, получив элемент, на который он указывает. Т& operator*() const; Разыменовать интеллектуальныйуказатель. private: Т *pointee; То, на что указывает }; интеллектуальныйуказатель. Здесь и конструктор копирования, и оператор присваивания являются открытыми. В интеллектуальных указателях, копирование и присваивание для которых запрещено, они обычно объявляются закрытыми. Два оператора разыменования определяются с атрибутом const, поскольку разыменование указателя не изменяет его (хотя и может привести к модификации того, на что он указывает). И наконец, каждый интеллектуальный указатель на объект Т реализован так, что он содержит внутри себя простой указатель на Т, который, собственно, и ссылается на объект. Прежде чем перейти к деталям реализации интеллектуальных указателей, стоит обсудить, как клиенты могут их использовать. Рассмотрим распределенную систему, в которой одни объекты являются локальными, а другие удаленными. Доступ к локальным объектам обычно выполняется быстрее и проще, чем к удаленным, поскольку удаленный доступ может потребовать удаленного вызова процедур или еще какого-либо механизма взаимодействия с удаленным компьютером. Программистам, пишущим код приложения, несомненно, мешает различие в работе с локальными и удаленными объектами. Более удобно было бы, если бы казалось, что все объекты находятся в одном месте. Применение интеллектуальных указателей в библиотеке позволяет создавать такую иллюзию: template<class Т> class DBPtr { public: DBPtr (Т *realPtr =0) DBPtr(DataBaselD id) , Шаблон для интеллектуальных указателей на объекты в распределенной базе данных. Создать интеллектуальный указатель на объект базы данных на основе простого локального указателя на него. Создать интеллектуальный class Tuple { public: указатель на объект базы данных 11 па основе уникального идентификатора в базе данных. Остальные функции интеллектуального указателя реализуются, как изложено выше. Класс для кортежей базы данных. void displayEditDialog( bool isValidO const; Вывести диалоговое окно, позволяюш;ее пользователю редактировать кортеж. Возвраш;ается, если указатель *this проходит проверку на достоверность. Шаблон класса для записи сведений об изменении объекта Т; подробнее см. ниже. template<class Т> class LogEntry { public: LogEntry(const T& objectToBeModifled); -LogEntry(); void editTuple(DBPtr<Tuple>& pt) { LogEntry<Tuple> entry(*pt), Сделать запись об этой операции редактирования. Подробнее см. ниже. Выводить диалоговое окно редактирования, пока не будут указаны правильные значения. do { pt->displayEditDialog() } while (pt->isValid() == false) Кортеж (tuple), редактируемый в функции EditTuple, может быть размещен на удаленном компьютере, но программист, который пишет функцию, не должен беспокоиться об этом; класс интеллектуального указателя скрывает данное свойство системы. С точки зрения программиста доступ ко всем кортежам осуществляется при помощи объектов, которые после объявления ведут себя в точности как обычные указатели. Обратите внимание на использование в функции editTuple объекта Log-Entry. Более традиционным было бы окружить вызов функции display-EditDialogue вызовами для начала и окончания записи. В вышеприведенном примере запись начинается с конструктора LogEntry, а заканчивается его деструктором. Как объясняется в правиле 9, обращение к объекту в начале и конце
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |