Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > smart pointer


Автор: cupper 1.6.2011, 22:04
Хотел бы немного подискутировать на тему умных указателей. А именно. Есть два типа умных указателей, с ручным подсчетом ссылок (addRef/releaseRef), и с автоматическим по типу shared_ptr. Удобство и смысл второго, для меня всецело понятен, и без него жизнь не мила. Суть первого понятна, но, удобством что то тут особо и не попахивает. Вернее я его не вижу.

Но, например если рассматривать конкретную задачу, библиотеку, то возможен такой случай:
есть некий главный класс Engine, есть некие другие классы например Session и Message. Библиотека дает возможность создать экземпляр Engine, но не дает возможности на прямую создавать Session и Message. Их можно создать только через экземпляр Engine, и получить указатель на них. Например для того что бы сугубо контролировать число и работу сессий через Engine.

Тогда получается следующая иерархия
Код

class Ref {public: addRef(); release()};

class Session : public Ref
{
protected:
   Session();
   ~virtual Session();
public:
   vrtual void virtualMethod() = 0;
};

class XSession : public Session
{
public:
    XSession();
    vrtual void virtualMethod() {};
protected:
   ~virtual XSession();
private::
    XSessionImpl* impl;
}

class XSessionImpl
{};


на ружу (доступны из библиотеки) у нас торчит только абстрактный Session. В самой же библиотеки работа ведется с XSession. Таким образом мы не даем пользователю возможности на прямую создавать экземпляры Session и предоставляем ему не голый указатель а smart pointer. Втиснуть в эту логику shared_ptr не получится, хотя бы из за того что у того кто будет пользоваться библиотекой boost'a не будет, ибо на C# нету его %) Ну или я просто недодумал как это сделать.

Теперь ваши примеры, и практика использования smile

Ахда, самое важное, когда я спросил можно ли я отойду от логики ручного подсчета и заюзаю shared_ptr (ну мол все равно ничего не изменить (это до того как я сообразил что все равно не выйдет заюзать)) я услышал в ответ нечто подобное "shared_ptr не нравиться, использую только когда не возможно intrusive использовать". Я помню что порой встречал ярые споры на тему что shared_ptr страшное зло и надо юзать там что то другое. Вот и решил углубиться и узнать мнения дгурих и перенять опыт, дабы слепо не махать тапками во время спора.

Автор: xvr 2.6.2011, 12:39
addRef/releaseRef применяется в реализации различных платформ, для встраивания в них GC. При этом объекты самой платформы обладают встроенным счетчиком ссылок, но предназначен он не для упрощения жизни самих объектов, а того, что платформа реализует.

Основное применение этого подхода - движки различных скриптовых (или byte code ориентированных) языков со встроенной GC. В этом случае объекты с addRef/releaseRef - это native реализация объектов языка, а пользователь этой функциональности - программа на этом самом скриптовом языке.

Второй пример - COM (и все, что от него растет).

Кстати, addRef/releaseRef никоим образом не мешает сделать поверх него аналог shared_ptr, для использования в самих объектах (или для прямой с ними работы). Яркий пример - COM + Atl CComPtr


Автор: cupper 2.6.2011, 22:01
Цитата(xvr @ 2.6.2011,  12:39)
addRef/releaseRef применяется в реализации различных платформ, для встраивания в них GC. При этом объекты самой платформы обладают встроенным счетчиком ссылок, но предназначен он не для упрощения жизни самих объектов, а того, что платформа реализует.

Основное применение этого подхода - движки различных скриптовых (или byte code ориентированных) языков со встроенной GC. В этом случае объекты с addRef/releaseRef - это native реализация объектов языка, а пользователь этой функциональности - программа на этом самом скриптовом языке.

Второй пример - COM (и все, что от него растет).

Кстати, addRef/releaseRef никоим образом не мешает сделать поверх него аналог shared_ptr, для использования в самих объектах (или для прямой с ними работы). Яркий пример - COM + Atl CComPtr

Я не знаю что такое GC, поэтому не понял о чем вы smile можно ссылку ? 

То что над addRef/release можно сделать умную обертку это само собой понятно, во только это как то нелепо выглядит: "умный указатель для умного указателя".

Автор: xvr 2.6.2011, 22:14
Цитата(cupper @  2.6.2011,  22:01 Найти цитируемый пост)
Я не знаю что такое GC, поэтому не понял о чем вы

Это Garbage Collection, по русски будет 'Сборка мусора'. 'Умные поинтеры' - это один из способов реализации этой самой GC
Цитата(cupper @  2.6.2011,  22:01 Найти цитируемый пост)
То что над addRef/release можно сделать умную обертку это само собой понятно, 

Ну так собственно и делают. Сами addRef/release лиш дают возможность, но не обеспечивают автоматическую сборку мусора/удаление неиспользуемых объектов. А вот обвернутые вокруг них smart pointer'ы обеспечивают.
Цитата(cupper @  2.6.2011,  22:01 Найти цитируемый пост)
во только это как то нелепо выглядит: "умный указатель для умного указателя". 

Нормально это выглядит, я уже упоминал - CComPtr в Atl. Аналоги есть в MFC, VCL (по видимому и в Qt). А в Object Pascal (a-la Delphi) их встроили на уровне языка. На голых addRef/release работают лишь если эти объекты можно пересчитать по пальцам и место их использования можно охватить одним взглядом на экран. Ну и еще настоящие мазохисты  smile 
Явное использование addRef/release на уровне объектов (без враперов) более провоцирует на ошибки, чем позволяет реализовать полноценный GC

Автор: kemiisto 2.6.2011, 23:04
Цитата(xvr @  2.6.2011,  21:14 Найти цитируемый пост)
Это Garbage Collection, по русски будет 'Сборка мусора'. 'Умные поинтеры' - это один из способов реализации этой самой GC

Более удачным (как, например, http://www.ibm.com/developerworks/linux/library/l-memory/) будет деление механизмов управления памятью на три группы
  • ручное (manual memory management);
  • полуавтоматическое (semi-automatic memory management, иногда semi-manual);
  • автоматическое (automatic memory management).
Умные указатели попадают во вторую группу, сборка мусора - в третью.

Автор: bsa 3.6.2011, 12:17
Цитата(xvr @  2.6.2011,  22:14 Найти цитируемый пост)
по видимому и в Qt

Что-то не видел я такого. Там есть QSharedPointer, аналог boost::shared_ptr.
Если где-то и используется addRef/release, то это скрыто глубоко в недрах платформозависимого кода и наружу не выходит.
Цитата(xvr @  2.6.2011,  22:14 Найти цитируемый пост)
Явное использование addRef/release на уровне объектов (без враперов) более провоцирует на ошибки, чем позволяет реализовать полноценный GC
Думаю, что addRef/release пришло из С. Например, в OpenSSL именно так реализуется модель COW при работе с большими числами. Возможности сделать полноценный конструктор/деструктор нет, вот народ и делал, что мог.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)