簡體   English   中英

C ++ 11在Lambda中捕獲成員變量

[英]C++11 Capture Member Variable in Lambda

我有一個成員變量定義為:

HWND WindowHandle。

我正在嘗試捕獲變量並在Lambda中分配它。 所以編譯器給了我一個警告,並建議我捕獲“這個”。 我做了,但現在Handle只在Lambda中有效:S換句話說,它在Lambda之外是NULL。

class Foo
{
    private:
        HWND WindowHandle;

    public:
        Foo();
        void MakeWindow(.......);
        HWND GetWindowHandle() {return WindowHandle;};
};

Foo::Foo(){}

Foo::MakeWindow(.......)
{
    Thread = std::thread([ClassName, Title, Width, Height, this]{
                    WindowHandle = CreateWindowEx(0, ClassName.c_str(), Title.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, Width, Height, 0, 0, GetModuleHandle(NULL), 0);
                    if(WindowHandle)
                    {
                        ShowWindow(WindowHandle, SW_SHOWDEFAULT);
                        MSG msg;
                        while(GetMessage(&msg, 0, 0, 0))
                            DispatchMessage(&msg);
                    }
                });
}


int main()
{
    Foo F;
    F.MakeWindow(........);
    std::cout<<std::boolalpha<<(F.GetWindowHandle() == NULL);  //writes true.
}

以上創建窗口完美! 它只是Handle為null。 如何從Lambda中獲取Handle到我的班級成員?

那是因為你的代碼有競爭條件。 當你檢查main()中的值時,線程還沒有運行,所以WindowHandle仍然是NULL。

除非你還沒有真正啟動線程。 在這種情況下,由於線程尚未執行,因此WindowHandle仍為NULL。

無論如何,您需要在具有互斥鎖的線程之間同步對WindowHandle的訪問。

您只能捕獲局部變量,即在創建lambda的函數中聲明的內容或其參數之一。 在訪問成員x時的成員函數中,實際上是訪問this->xthis是指向傳遞給成員函數的對象的隱式指針。 因此,lambda將捕獲this而不是x 要捕獲成員,您需要創建一個包含它的局部變量,然后捕獲此變量,例如:

auto&& tmpWindowHandle = this->WindowHandle; // ... or just WindowHandle

...然后你將在lambda函數中捕獲tmpWindowHandle

由於你的lambda函數沒有顯示任何同步,你的GetWindowHandle()似乎也沒有任何同步,你的調用線程可能會在你被線程設置之前訪問WindowHandle成員:你需要某種形式的同步,它可以是一個join()或某種形式的互斥或條件變量,然后才能調用其他一些線程使用WindowHandle 整體設置看起來像是std::future<...>的良好應用:它旨在可能同時運行一個函數然后阻塞,直到實際訪問結果時需要結果。

您正在不同的線程上分配WindowHandle 所以可能發生的事情是你的新線程還沒有啟動,你正在檢查WindowHandle是否已經改變。 此外,您應該使用某些互斥鎖或其他構造來保護對WindowHandle訪問,否則您將遇到競爭條件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM