std::unique_ptr with custom deleter for win32 LocalFree

后端 未结 4 957
离开以前
离开以前 2021-02-12 23:24

I have the win32 API CommandLineToArgvW which returns a LPWSTR* and warns me that

CommandLineToArgvW allocates a

相关标签:
4条回答
  • 2021-02-12 23:55

    I find shared_ptr a bit more useful as a generic resource guard. It does not require the deleter to be the part of template arguments and as such can be easily passed around.

    std::shared_ptr<LPWSTR> p(
        ::CommandLineToArgvW(L"cmd.exe p1 p2 p3", &n),
        ::LocalFree);
    
    0 讨论(0)
  • 2021-02-13 00:12

    It looks correct to me. You could make it a little more succinct by specifying the unique_ptr's deleter inline rather than creating a functor for it.

    std::unique_ptr<LPWSTR, HLOCAL(__stdcall *)(HLOCAL)> 
          p( ::CommandLineToArgvW( L"cmd.exe p1 p2 p3", &n ), ::LocalFree );
    

    Or, if you don't want to mess with LocalFree's signature and calling conventions you can use a lambda to do the deletion.

    std::unique_ptr<LPWSTR, void(*)(LPWSTR *)> 
          p( ::CommandLineToArgvW( L"cmd.exe p1 p2 p3", &n ), 
             [](LPWSTR *ptr){ ::LocalFree( ptr ); } );
    

    Note: At the time this answer was first written, VS2010 was the released VS version available. It doesn't support conversion of capture-less lambdas to function pointers, so you'd have to use std::function in the second example

    std::unique_ptr<LPWSTR, std::function<void(LPWSTR *)>> 
          p( ::CommandLineToArgvW( L"cmd.exe p1 p2 p3", &n ), 
             [](LPWSTR *ptr){ ::LocalFree( ptr ); } );
    
    0 讨论(0)
  • 2021-02-13 00:13

    And what about an answer using Microsoft Windows Implementation Libraries (WIL)?

    First of all "install" WIL (from a terminal):

    c:\dev>git clone https://github.com/microsoft/wil.git
    

    And then:

    #include <Windows.h>
    #include <iostream>
    
    #include "c:/dev/wil/include/wil/resource.h"
    
    int main(int argc, char* argv[])
    {
       {
          int n = 0;
          wil::unique_hlocal_ptr<LPWSTR> p(::CommandLineToArgvW(L"cmd.exe p1 p2 p3", &n));
          for (int i = 0; i < n; i++) {
             std::wcout << p.get()[i] << L"\n";
          }
       }
    
       return 0;
    }
    
    0 讨论(0)
  • 2021-02-13 00:15

    Declaring of custom deleter is not so pretty, use of decltype() is faster. std::shared_ptr is an alternative, but it is larger than std::unique_ptr. If you don't want to share a pointer, then take a unique_ptr.

    std::unique_ptr<LPWSTR, decltype(::LocalFree)> 
         p( ::CommandLineToArgvW( L"cmd.exe p1 p2 p3", &n ), ::LocalFree );
    
    0 讨论(0)
提交回复
热议问题