|
Программирование >> Перегруженные имена функций и идентификаторы
MCPtr(const MPtr<T>& p); MCPtr(const MCPtr<T>& p); ~MCPtr(); const T* operator->() const; operator const T*() const; MCPtr<T>& operator=(const MPtr<T>& p) MCPtr<T>& operator=(const MCPtr<T>& p); protected: MPtr<T> ptr; private: MCPtr(); Во-первых, это надстройка (адаптер) над обычным указателем. А во-вторых, его главное отличие, это то, что operator-> возвращает константный указатель, а не обычный. Это очень просто и, на самом деле, очень полезно: все дело в том, что это дает использовать объект в двух контекстах - там, где его можно изменять (скажем, внутри другого объекта, где он был создан) и там, где можно пользоваться лишь константным интерфейсом (т.е., где изменять нельзя; к примеру, снаружи объекта-фабрики). Это разумно вытекает из простых константных указателей. Для того, чтобы пользоваться MCPtr требуется единственное (хотя и достаточно строгое) условие: во всех классах должна быть корректно расставлена константность методов. Вообще, это - признак профессионального программиста: использование модификатора const при описании методов. Как правило используют умные указатели в том, что называется фабриками объектов (или, в частности, производящими функциями): т.е., дя того, чтобы вернуть объект, удовлетворяющий какому-то интерфейсу. При использовании подобного рода указателей клиентской части становится очень удобно - опускаются все проблемы, связанные с тем, когда можно удалить объект, а когда нельзя (скажем, при совместном использовании одного и того же объекта разными клиентами - клиенты не обязаны знать о существовании друг друга). Помимо всего прочего, переопределение селектора позволяет простым образом вставить синхронизацию при создании многопоточных приложений. Вообще, подобные обертки чрезвычайно полезны, им можно найти массу применений. Несомненно, использовать умные указатели необходимо с осторожностью. Все дело в том, что, как у всякой простой идеи, у нее есть один очень большой недостаток: несложно придумать пример, в котором два объекта ссылаются друг на друга через умные указатели и... никогда не будут удалены. Почему? Потому что счетчики сс1лок у них всегда будут как минимум 1, при том, что снаружи на них никто не ссылается. Есть рекомендации по поводу того, как распознавать такие ситуации во время выполнения программы, но они очень громоздки и, поэтому не годятся к применению. Ведь что прельщает в умных указателях? Простота. Фактически, ничего лишнего, а сколько можно при желании извлечь пользы из их применения. Посему надо тщательно следить еще на стадии проектирования за тем, чтобы подобных цепочек не могло бы возникнуть в принципе. Потому как если такая возможность будет, то в конце концов она проявит себя. Умные указатели активно используются в отображении COM-объектов и CORBA-объектов на C++: они позволяют прозрачно для программиста организовать работу с объектами, которые реально написаны на другом языке программирования и выполняются на другой стороне земного шара. Техника подсчета ссылок в явном виде (через вызов методов интерфейса AddRef() и Release()) используется в технологии COM. Еще стоит сказать про эффективность использования умных указателей. Возможно, это кого-то удивит, но затраты на их использование при выполнении программы минимальны. Почему? Потому что используются шаблоны, а все методы-чены классов (и, в особенности селектор) конечно же объявлены как inline. Подсчет сс1лок не сказывается на обращении к объекту, только на копировании указателей, а это не такая частая операция. Ясно, что использование шаблонов усложняет работу компилятора, но это не так важно. Рассуждения на тему Умных указателей При изучении С++, не раз можно встретиться с умными указателями. Они встречаются везде и все время в разнгх вариантах. Без стандартизации. Вообще, мысль об упрощении себе жизни вертится в головах программистов всегда: Лень - двигатель прогресса . Поэтому и были придуманы не просто указатели, а такие из них, которые брали часть умственного напряга на себя, тем самым, делая вид, что они нужны. Итак, что такое SmartPointer-ы? По сути это такие классы, которые умеют чуть больше... - а в общем, смотрим пример: class A private: int count; public: A(){count = 0;} void addref(){count++;} void release(){if(--count == 0) delete this;} protected: ~A(); public: void do something(){cout << Hello ;} Сначала придумали внутри объекта считать ссылки на него из других объектов при помощи механизма подсчета ссылок . Суть здесь в том, что когда вы сохраняете ссылку на объект, то должны вызвать для него addref, а когда избавляетесь от объекта, то вызвать release. Сложно? Совсем нет - это дело привычки. Таким образом, объект умеет сам себя удалять. Здорово? Так оно и есть. Кстати такой объект может существовать только в куче, поскольку деструктор в защищенной зоне и по той же причине нельзя самому сделать delete a обойдя release. Теперь переходим к собственно самим умным указателям и опять пример: class PA
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |