std:: уникальный ptr с пользовательским удалителем для win32 LocalFree
у меня есть win32 API CommandLineToArgvW
возвращает LPWSTR*
и
предупреждает меня, что
CommandLineToArgvW
выделяет блок непрерывной памяти для указатели на строки аргументов и для строк аргументов себя; вызывающее приложение должно освободить память, используемую список аргументов, когда он больше не нужен. Чтобы освободить память, используйте один звонок вLocalFree
функция.
посмотреть http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391(v=vs. 85).aspx
что такое c++ идиоматический способ освободить память в приведенном выше случае?
Я думал о std::unique_ptr
с пользовательским deleter, что-то вроде этого:
#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;
}
есть ли какие-либо проблемы в приведенном выше коде?
3 ответов
мне кажется, это правильно. Вы можете сделать его немного более кратким, указав unique_ptr
's deleter inline, а не создание функтора для него.
std::unique_ptr<LPWSTR, HLOCAL(__stdcall *)(HLOCAL)>
p( ::CommandLineToArgvW( L"cmd.exe p1 p2 p3", &n ), ::LocalFree );
или, если вы не хотите возиться с LocalFree
подписи и вызывающие соглашения вы можете использовать лямбда для удаления.
std::unique_ptr<LPWSTR, void(*)(LPWSTR *)>
p( ::CommandLineToArgvW( L"cmd.exe p1 p2 p3", &n ),
[](LPWSTR *ptr){ ::LocalFree( ptr ); } );
Примечание: в то время, когда этот ответ был впервые написан, 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
немного полезнее в качестве универсального защитника ресурсов. Он не требует, чтобы делетер был частью аргументов шаблона и как таковой может быть легко передан.
std::shared_ptr<LPWSTR> p(
::CommandLineToArgvW(L"cmd.exe p1 p2 p3", &n),
::LocalFree);