std :: unique_ptr,带有win32 LocalFree的自定义删除器

Ale*_*son 16 c++ winapi memory-management unique-ptr c++11

我有win32 API CommandLineToArgvW返回LPWSTR*并警告我

CommandLineToArgvW为参数字符串的指针和参数字符串本身分配一块连续的内存; 当不再需要时,调用应用程序必须释放参数列表使用的内存.要释放内存,请使用单个调用LocalFree函数.

请参阅 http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391(v=vs.85).aspx

在上述情况下,什么是释放内存的C++惯用方法?

我正在考虑std::unique_ptr使用自定义删除器,类似的东西:

#include <Windows.h>
#include <memory>
#include <iostream>

template< class T >
struct Local_Del
{
   void operator()(T*p){::LocalFree(p);}
};

int main(int argc, char* argv[])
{
   {
      int n = 0;
      std::unique_ptr< LPWSTR, Local_Del< 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;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码有什么问题吗?

Pra*_*ian 10

它对我来说是正确的.你可以通过指定unique_ptr内联的删除器而不是为它创建一个仿函数来使它更简洁.

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

或者,如果您不想使用LocalFree签名和调用约定,可以使用lambda进行删除.

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

注意:在第一次写这个答案时,VS2010是已发布的VS版本.它不支持将无捕获的lambda转换为函数指针,因此您必须std::function在第二个示例中使用它

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


Ale*_*hel 6

声明自定义删除器并不是那么漂亮,使用decltype()速度更快.std::shared_ptr是一种替代方案,但它大于std::unique_ptr.如果你不想共享一个指针,那么拿一个unique_ptr.

std::unique_ptr<LPWSTR, decltype(::LocalFree)> 
     p( ::CommandLineToArgvW( L"cmd.exe p1 p2 p3", &n ), ::LocalFree );
Run Code Online (Sandbox Code Playgroud)

  • 在Visual Studio 2010上,它必须是`std :: unique_ptr <LPWSTR,decltype(&:: LocalFree)>`,否则构建将失败并出现神秘错误.那是因为`decltype(:: LocalFree)`不是函数指针类型,而是函数类型. (4认同)

小智 5

我发现shared_ptr作为通用资源保护更有用.它不需要删除器作为模板参数的一部分,因此可以很容易地传递.

std::shared_ptr<LPWSTR> p(
    ::CommandLineToArgvW(L"cmd.exe p1 p2 p3", &n),
    ::LocalFree);
Run Code Online (Sandbox Code Playgroud)