2012-03-27 60 views
13

我在Win32 API CommandLineToArgvW返回一個LPWSTR*和 警告我說,的std ::的unique_ptr同爲Win32 LocalFree定製刪除

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

有沒有在上面的代碼中的任何問題嗎?

回答

10

它看起來對我很正確。通過內聯指定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可用的版本。它doesn't support轉換捕獲少的lambda表達式到函數指針,所以你必須在第二個例子中

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

你不需要'std :: function'作爲最後一個例子,我想:無狀態的lambda可以轉換爲函數指針。即'std :: unique_ptr p(...)' – MSalters 2012-03-27 18:20:06

+0

@MSalters我嘗試過,但是在VC10和g ++ 4.6.2下編譯失敗。前者的錯誤信息是'error C2664:'std :: unique_ptr <_Ty,_Dx> :: unique_ptr(wchar_t *,void(__stdcall * const&)(LPWSTR *))':不能從'匿名命名空間'轉換參數2 :: '到'void(__stdcall * const&)(LPWSTR *)' – Praetorian 2012-03-27 18:25:41

+0

@MSalters你是對的,捕獲的lambdas可以轉換爲函數指針,所以'std :: function'不是必需的。但是,VC10 [不實現此](https://connect.microsoft.com/VisualStudio/feedback/details/572138)。不知道我第一次嘗試使用g ++是如何搞砸的,但它確實有效。 – Praetorian 2012-03-27 22:32:06

4

使用std::function我發現shared_ptr多一點有用的通用資源保護裝置。它不要求刪除器是模板參數的一部分,因此可以輕鬆地傳遞。

std::shared_ptr<LPWSTR> p(
    ::CommandLineToArgvW(L"cmd.exe p1 p2 p3", &n), 
    ::LocalFree); 
+1

謝謝你的回答。我不太確定我更喜歡簡單的語法而不是正確的語義。恕我直言shared_ptr不適合我的情況。請參閱http://www2.research.att.com/~bs/C++0xFAQ.html#std-shared_ptr vs http://www2.research.att.com/~bs/C++0xFAQ.html#std -unique_ptr – 2012-04-01 08:41:36

+0

的確,您並不是想要傳遞指針,但瞭解相關技術可能會有幫助。 – 2012-04-02 21:56:51

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); 
+1

在Visual Studio 2010上,它必須是'std :: unique_ptr ',否則構建將會失敗並帶有隱晦的錯誤。這是因爲'decltype(:: LocalFree)'不是一個函數指針類型,而是一個函數類型。 – 2013-10-03 13:30:38

相關問題