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

匿名 (未验证) 提交于 2019-12-03 01:47:02

问题:

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 specific handle_trats that calls CloseHandle. The problem is that HANDLE is defined as void* unique_ptr won't compile as sizeof(void) is not defined.

So far I see only two possibilities:

  1. Create a wrapper class for HANDLEs and use it like this: unique_ptr. This pretty much makes the unique_ptr itself useless.
  2. Use HANDLE specific smart pointer class that resembles unique_ptr.

What do you think is better choice? What would you suggest?

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

回答1:

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 void operator()(T* ptr) {         ptr->Release();     } }; unique_ptr ptr; // Works fine

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



回答2:

Create a specific smart pointer class, won't take long. Don't abuse library classes. Handle semantics is quite different from that of a C++ pointer; for one thing, dereferencing a HANDLE makes no sense.

One more reason to use a custom smart handle class - NULL does not always mean an empty handle. Sometimes it's INVALID_HANDLE_VALUE, which is not the same (actually -1).



回答3:

You can typedef your unique_ptr with a custom deleter

struct handle_deleter {     void operator()(void* handle)     {         if(handle != nullptr)             CloseHandle(handle);     } };  typedef std::unique_ptr UniqueHandle_t; UniqueHandle_t ptr(CreateFile(...));


回答4:

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);


回答5:

I don't recommend using smart pointers with handles.

I recommend you to take a look at A Proposal to Add additional RAII Wrappers to the Standard Library and at the drawbacks of using smart pointers with handles.

Personally, I'm making use of the reference implementation of that proposal instead of using std::unique_ptr for these situations.



回答6:

yet another solution

std::unique_ptr uniqueHandle( file, []( HANDLE h ) { ::CloseHandle( h ); } );


回答7:

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

std::unique_ptr 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.



回答8:

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



回答9:

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.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!