18

CommandLineToArgvW我有返回 aLPWSTR*并警告我的 win32 API

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

上面的代码有问题吗?

4

4 回答 4

11

在我看来是正确的。unique_ptr您可以通过内联指定 ' 删除器而不是为其创建函子来使其更简洁。

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

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

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

注意:在首次编写此答案时,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 ); } );
于 2012-03-27T16:09:23.533 回答
7

自定义删除器的声明不是那么漂亮,使用起来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 );
于 2013-02-25T12:56:44.450 回答
5

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

std::shared_ptr<LPWSTR> p(
    ::CommandLineToArgvW(L"cmd.exe p1 p2 p3", &n),
    ::LocalFree);
于 2012-04-01T08:30:00.053 回答
0

那么使用Microsoft Windows 实现库 (WIL)的答案呢?

首先“安装”WIL(从终端):

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

接着:

#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;
}
于 2020-04-23T13:50:53.150 回答