Using std::make_unique with a custom deleter

后端 未结 3 1156
栀梦
栀梦 2020-12-17 08:02

In using std::unique_ptr with a custom deleter I desire to use std::make_unique rather than a raw new. I am using VC++2013. It appears to me that

相关标签:
3条回答
  • 2020-12-17 08:12

    As far as I know there is no make_unique function in the C++11 standard. See

    • Why does C++11 have `make_shared` but not `make_unique`
    • make_unique and perfect forwarding

    So I would assume that the make_unique is an implementation from Microsoft that is at least not included in the standard.

    But nevertheless you can use a custom deleter with unique_ptr. When using unique_ptr you have to specify the type of the deleter as a second template argument and then pass an appropriate object to the constructor.

    0 讨论(0)
  • 2020-12-17 08:29

    The whole point of make_unique is to encapsulate the notion of "use new to create a T from given constructor arguments and use delete to destroy it".

    If you wanted a custom deleter, you would also have to specify how to create the object, and then there would be nothing more gained from having the emplacing maker function.

    I wrote some examples of custom maker functions for certain unique resource handles in this post.

    0 讨论(0)
  • 2020-12-17 08:29

    Here is a way to wrap c style memory management into a std::unique_ptr using a custom deleter that calls a custom free function. This has a make function helper similar to 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;
    }
    

    Possible output:

    main:48 ptr=50511440
    foo:40 ptr=50511440
    MY_free:20 ptr=50511440
    main:53 ptr=0
    
    0 讨论(0)
提交回复
热议问题