我有win32的API CommandLineToArgvW
其中返回一个 LPWSTR*
并警告我说
CommandLineToArgvW
为指向参数字符串的指针和参数字符串本身分配一个连续的内存块;当参数列表不再需要时,调用应用程序必须释放参数列表使用的内存。要释放内存,请使用一个对LocalFree
功能。
见http:/msdn.microsoft.comen-uslibrarywindowsdesktopbb776391(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;
}
上面的代码有什么问题吗?
在我看来是正确的。你可以把它弄得更简洁一些,通过指定的 unique_ptr
的 deleter inline,而不是为它创建一个漏斗。
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版本。 在这个答案第一次写的时候,VS2010是发布的VS版本。它 不支持 将无捕获的lambdas转换为函数指针,所以你必须使用 std::function
在第二个例子中
std::unique_ptr<LPWSTR, std::function<void(LPWSTR *)>>
p( ::CommandLineToArgvW( L"cmd.exe p1 p2 p3", &n ),
[](LPWSTR *ptr){ ::LocalFree( ptr ); } );
自定义deleter的声明并不那么漂亮,使用的是 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 );
我发现 shared_ptr
作为一个通用的资源保护器,它更有用一些。它不要求deleter是模板参数的一部分,因此可以很容易地传递。
std::shared_ptr<LPWSTR> p(
::CommandLineToArgvW(L"cmd.exe p1 p2 p3", &n),
::LocalFree);
那么使用 微软视窗执行库(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;
}