À l'aide de std::unique_ptr
avec un suppresseur personnalisé que je souhaite utiliser std::make_unique
plutôt qu'un nouveau brut. J'utilise VC++ 2013. Il me semble qu'il n'y a aucun moyen d'utiliser std::unique_ptr
si vous utilisez un suppresseur personnalisé. Ai-je raté quelque chose ou est-ce vraiment le cas?
Information additionnelle:
J'utilise un std::unique_ptr<HANDLE, custom_deleter>
pour contenir un HANDLE Windows pour un port COM ouvert.
Je pourrais écrire une classe RAII personnalisée pour cela, et ce ne serait pas terriblement difficile, mais je voyais à quel point ce serait difficile/difficile/mauvais d'utiliser std::unique_ptr
.
Tout l'intérêt de make_unique
consiste à encapsuler la notion d '"utiliser new
pour créer un T
à partir d'arguments constructeurs donnés et utiliser delete
pour le détruire ".
Si vous vouliez un suppresseur personnalisé, vous devrez également spécifier comment créer l'objet, et alors il n'y aurait rien de plus à gagner avec le fabricant de placement fonction.
J'ai écrit quelques exemples de fonctions de création personnalisées pour certains descripteurs de ressources uniques dans cet article .
Voici un moyen d'encapsuler la gestion de la mémoire de style c dans un std::unique_ptr
en utilisant un suppresseur personnalisé qui appelle une fonction libre personnalisée. Cela a une aide de fonction make similaire à std::make_unique
LIVE :
#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;
}
Sortie possible:
main:48 ptr=50511440 foo:40 ptr=50511440 MY_free:20 ptr=50511440 main:53 ptr=0