Использование deallocator & allocator в shared_ptr - PullRequest
4 голосов
/ 24 февраля 2012

Я использую несколько библиотечных функций, которые возвращают указатель, созданный с использованием malloc или new.Итак, у меня есть собственный клиентский диллокатор, основанный на том, какой тип распределения использовался.

Например,

shared_ptr<int> ptr1(LibFunctA(), &MallocDeleter); //LibFunctA returns pointer created using malloc
shared_ptr<int> ptr2(LibFunctB(), &newDeleter);  //LibFunctB returns pointer created using new

Теперь я понимаю, что это очень наивное использование вышеуказанного деаллокатора, но какие другие сценарииинтенсивно ли он используется для?

Кроме того, как можно использовать распределитель клиентов?Я попытался назначить пользовательский распределитель, как показано ниже, но теперь как мне его вызвать?Где эта функция помогает?

shared_ptr<int> ptr3(nullptr_t, &CustomDeleter, &CustomAllocator);  //assume both functs are defined somewhere.

Ответы [ 3 ]

6 голосов
/ 24 февраля 2012

Я не вижу ничего «наивного» в таком использовании средств удаления. Это главная цель функции в конце концов; уничтожить объекты указателя, которые не размещены с использованием стандартных методов C ++.

Распределители предназначены для случаев, когда вам нужно контролировать, как блок управления shared_ptr памяти выделяется и удаляется. Например, у вас может быть пул памяти, из которого вы хотите эти вещи, или если у вас ограниченная память, когда выделение памяти через new просто недопустимо. А поскольку тип управляющего блока до shared_ptr, нет другого способа контролировать его распределение, кроме как с помощью какого-либо типа распределителя.

3 голосов
/ 24 февраля 2012

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

shared_ptr<void> file(::CreateFileW(...), ::CloseHandle);

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

1 голос
/ 24 февраля 2012

Я думаю, что пользовательский распределитель будет использоваться для выделения пространства для объекта «с общим счетом», в котором хранится копия деаллокатора (удалителя) и счетчика ссылок.быть использованным для ...

Одно упоминание уже упоминалось: сделать shared_ptr совместимым с объектами, которые должны быть удалены какой-либо специальной функцией (например, FILE, которая удаляется fclose), без необходимостиоберните его во вспомогательный класс, который позаботится о правильном удалении.

Еще одно использование пользовательского средства удаления - пулы.Пул может выдать shared_ptr<T>, которые были инициализированы «специальным» удалителем, который на самом деле ничего не удаляет, но вместо этого возвращает объект в пул.

И еще одна вещь: удалитель уженеобходимо реализовать некоторые shared_ptr функции.Например, удаляемый тип всегда фиксируется во время создания и не зависит от типа инициализируемого shared_ptr.

Вы можете создать shared_ptr<Base>, фактически инициализировав его с Derived.shared_ptr гарантирует, что при удалении объекта он будет удален как Derived, даже если Base не имеет , а не имеет виртуального dtor.Чтобы сделать это возможным, shared_ptr уже должен хранить некоторую информацию о том, как объект должен быть удален.Таким образом, разрешение пользователю указать полностью настраиваемое средство удаления ничего не стоит (с точки зрения производительности во время выполнения) и не требует большого количества дополнительного кода.

Вероятно, существуют десятки других сценариев, в которых можно сделатьхорошее использование пользовательского удалителя, это то, что я до сих пор придумал.

...