Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

c++11

winapi

I was wondering if there is a way to use unique_ptr<T> 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<void> 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<new CHandle(h)>. This pretty much makes the unique_ptr<T> itself useless.
  2. Use HANDLE specific smart pointer class that resembles unique_ptr<T>.

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?

like image 824
devdimi Avatar asked Mar 23 '12 16:03

devdimi


People also ask

Why Auto_ptr is deprecated?

Why is auto_ptr deprecated? It takes ownership of the pointer in a way that no two pointers should contain the same object. Assignment transfers ownership and resets the rvalue auto pointer to a null pointer. Thus, they can't be used within STL containers due to the aforementioned inability to be copied.

Why should you use smart pointers instead of regular pointers?

The objects of the smart pointer class look like normal pointers. But, unlike Normal Pointers it can deallocate and free destroyed object memory. The idea is to take a class with a pointer, destructor and overloaded operators like * and ->.

Are smart pointers on the stack or heap?

As shown in the example, a smart pointer is a class template that you declare on the stack, and initialize by using a raw pointer that points to a heap-allocated object.

Do you need destructors with smart pointers?

Boost smart pointers by themselves don't have anything to do with the need for a destructor. All they do is remove the need for you to call delete on the allocated memory that they are effectively managing.


3 Answers

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.

like image 79
Puppy Avatar answered Oct 15 '22 11:10

Puppy


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

like image 31
Seva Alekseyev Avatar answered Oct 15 '22 09:10

Seva Alekseyev


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.

like image 44
Roman Kruglov Avatar answered Oct 15 '22 11:10

Roman Kruglov