Использование std :: make_unique с пользовательским средством удаления

В использовании std::unique_ptr с пользовательским удалителем я хочу использовать std::make_unique а не сырой новый. Я использую VC ++ 2013. Мне кажется, что нет возможности использовать std::unique_ptr если вы используете пользовательский удалитель. Я что-то пропустил или это действительно так?


Дополнительная информация:

Я использую std::unique_ptr<HANDLE, custom_deleter> держать Windows РУЧКУ для открытого COM-порта.

Я мог бы написать собственный класс RAII для этого, и это не было бы ужасно сложно, но я видел, как трудно / сложно / плохо это будет использовать std::unique_ptr,

19

Решение

Весь смысл make_unique это заключить в капсулу понятие «использование new создать T из заданных аргументов конструктора и использовать delete уничтожить его «.

Если вы хотите пользовательское удаление, вам также нужно будет указать, как Создайте объект, и тогда больше ничего не получится от наличия функции создателя создания.

Я написал несколько примеров пользовательских функций создателя для определенных уникальных дескрипторов ресурса. в этом посте.

21

Другие решения

Вот способ обернуть управление памятью в стиле c в std::unique_ptr использование пользовательского средства удаления, вызывающего пользовательскую бесплатную функцию. Это имеет вспомогательную функцию make, похожую на std::make_unique ЖИТЬ:

#include <iostream>
#include <functional>
#include <memory>

// Some C style code that has some custom free function ptr...
extern "C" {

struct ABC { };

enum free_type_e {
FREE_ALL,
FREE_SOME
};

typedef void (free_f)(enum free_type_e free_type, void *ptr);
struct some_c_ops { free_f* free_op; };

void MY_free(enum free_type_e free_type, void *ptr)
{
printf("%s:%d ptr=%ld\n", __func__, __LINE__, (long)ptr);
(void)free_type;
free(ptr);
}

}; // extern "C"
template<typename T>
using c_unique_ptr = std::unique_ptr<T,std::function<void(T*)>>;

template <typename T>
c_unique_ptr<T> make_c_unique(some_c_ops* op, free_type_e free_type)
{
return c_unique_ptr<T>(static_cast<T*>(calloc(1, sizeof(T))),
std::bind(op->free_op, free_type, std::placeholders::_1));
}

void foo(c_unique_ptr<ABC> ptr)
{
std::cout << __func__ << ":" << __LINE__
<< " ptr=" << reinterpret_cast<size_t>(ptr.get()) <<     std::endl;
}

int main()
{
some_c_ops ops = { MY_free };
c_unique_ptr<ABC> ptr = make_c_unique<ABC>(&ops, FREE_ALL);
std::cout << __func__ << ":" << __LINE__
<< " ptr=" << reinterpret_cast<size_t>(ptr.get()) << std::endl;

foo(std::move(ptr));

std::cout << __func__ << ":" << __LINE__
<< " ptr=" << reinterpret_cast<size_t>(ptr.get()) << std::endl;
}

Возможный вывод:

main:48 ptr=50511440
foo:40 ptr=50511440
MY_free:20 ptr=50511440
main:53 ptr=0
0

Насколько я знаю, нет make_unique функция в стандарте C ++ 11. Увидеть

Так что я бы предположил, что make_unique это реализация от Microsoft, которая, по крайней мере, не включена в стандарт.

Но тем не менее вы можете использовать пользовательский удалитель с unique_ptr, Когда используешь unique_ptr Вы должны указать тип удалителя в качестве второго аргумента шаблона, а затем передать соответствующий объект конструктору.

-1
По вопросам рекламы [email protected]