std::unique_ptr for Windows handles

To close a Windows handle with std::unique_ptr, we need to define a type with operator() and specify it as the second template parameter.

struct Deleter
    // By defining the pointer type, we can delete a type other than T*.
    // In other words, we can declare unique_ptr<HANDLE, Deleter> instead of
    // unique_ptr<void, Deleter> which leaks the HANDLE abstraction.
    typedef HANDLE pointer;

    void operator()(HANDLE h)
        if(h != INVALID_HANDLE_VALUE)

void OpenAndWriteFile()
    // Specify a deleter as a template argument.
    std::unique_ptr<HANDLE, Deleter> file(CreateFile(_T("test.txt"),
    if(file.get() != INVALID_HANDLE_VALUE)
        DWORD size;
        WriteFile(file.get(), "Hello World", 11, &size, NULL);

This is different from std::shared_ptr where we can just specify the functor in a constructor parameter.

    std::shared_ptr<void> file(CreateFile(_T("test.txt"),
                                CloseHandle);   // Specify deleter functor as a constructor parameter.

Although it’s extra work to define a new deleter type, std::unique_ptr has following advantage.

First, the smart pointer object doesn’t have to keep the deleter object, thus the size of the pointer becomes smaller. In fact, std::unique_ptr occupies the just same size as T*.

Second, Application can overwrite the pointer type. It means we can write:

std::unique_ptr<HANDLE, Deleter> foo(...);

instead of this HANDLE abstraction leakage version.

std::unique_ptr<void, Deleter> foo(...);

About Moto

Engineer who likes coding
This entry was posted in C++ and tagged , . Bookmark the permalink.

4 Responses to std::unique_ptr for Windows handles

  1. Brad says:

    Thanks, Moto.

    I have two questions:
    1) Can you clarify your comment in the code? It’s the thing I’m trying to understand, but there’s a grammatical error in the and I can’t deduce what you mean: “we can use delete a type other than T*”) ???

    2) How does defining the pointer type help, when you never use it in your example? Is there some sort of side-effect from the declaration?


  2. Brad says:

    Also, when I try something similar:
    struct VolumeHandleDeleter
    void operator()( HANDLE volH )
    if( volH )
    FindVolumeClose( volH );
    typedef std::unique_ptr unique_vol_handle_t;

    In main():
    unique_vol_handle_t volH( FindFirstVolumeW( buffer, MAX_GUID_PATH ) ) );
    VS2012 gives me:
    1> error C2664: ‘std::unique_ptr::unique_ptr(std::nullptr_t) throw()’ : cannot convert parameter 1 from ‘HANDLE’ to ‘std::nullptr_t’
    1> with
    1> [
    1> _Ty=HANDLE,
    1> _Dx=VolumeHandleDeleter
    1> ]
    1> nullptr can only be converted to pointer or handle types

    referencing my volH declaration in main(). Any thoughts?

    FindFirstVolumeW returns HANDLE.

  3. Brad says:

    Well I’ll be… Adding the typedef resolves the issue.

    No idea why, so I’ve posted this as a StackOverflow question at

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s