How to use C++ standard smart pointers with Windows HANDLEs?

后端 未结 10 1089
Happy的楠姐
Happy的楠姐 2020-12-17 19:04

I was wondering if there is a way to use unique_ptr with Windows HANDLEs?

I was thinking to replace the std::default_delete with s

相关标签:
10条回答
  • 2020-12-17 19:39

    inspired by Alexander Drichel's solution, here is even shorter

    std::unique_ptr< HANDLE, decltype(&CloseHandle) > uniqueHandle( nullptr, CloseHandle );
    

    Works in MSVC 2010. Note that you need to specify '&' for the function name in decltype() to deduce a pointer-to-function type.

    0 讨论(0)
  • 2020-12-17 19:42

    You can create a Deleter class that will release the handle instead of calling delete().

    You can see in this LINK how they've solved deleting arrays with a shared_ptr (unique_ptr also has a constructor that recieves a Delete class)

      struct handle_deleter
      {   
        void operator ()( HANDLE handle)
          { CloseHandle(p); }
      };
    
      HANDLE blah = GetSomeHandle();
      unique_ptr myPointer(blah,handle_deleter);
    
    0 讨论(0)
  • 2020-12-17 19:43

    A HANDLE does not always close with CloseHandle(), beware. For example a HANDLE opened with FindNextFile() must be closed by FindClose().

    0 讨论(0)
  • 2020-12-17 19:47

    Here is a handy little "custom_ptr" I use for dealing with a HANDLE. C++17 is required in order for this to compile. This idea was lifted from another SO post, I only added the std::remove_pointer_t<T> so that I wouldn't have to pass void as the custom_ptr type parameter.

    Definition

    #include <type_traits>
    #include <memory>
    
    template<auto fn>
    using deleter_from_fn = std::integral_constant<decltype( fn ), fn>;
    
    template<typename T, auto fn>
    using custom_ptr = std::unique_ptr<typename std::remove_pointer_t<T>, deleter_from_fn<fn>>;
    

    Use

    custom_ptr<HANDLE, &CloseHandle> phandle{
        CreateFileMapping( INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, 1024, L"FileName" ) };
    
    0 讨论(0)
  • 2020-12-17 19:50

    The question can be extended for COM IUnknown pointers - can CComPtr be replaced by any of the standard smart pointers?

    Yes. You don't specialize std::default_deleter, you simply replace the deleter type.

    struct COMDeleter {
        template<typename T> void operator()(T* ptr) {
            ptr->Release();
        }
    };
    unique_ptr<IUnknown, COMDeleter> ptr; // Works fine
    

    The same principle applies to shared_ptr and indeed, to HANDLE.

    0 讨论(0)
  • 2020-12-17 19:50

    You must use CloseHandle() to "close" a handle instead using delete. They will be deleted by Windows as soon as they are not opened elsewhere. So you could write a wrapper that calls CloseHandle() instead of deleteing it. You could also write your own smartpointer class which might be better as there is no need of a wrapper anymore.

    0 讨论(0)
提交回复
热议问题