簡體   English   中英

c ++:MSVC與GCC + CLANG:處理lambdas捕獲類成員變量,正確的方法是什么?

[英]c++: MSVC vs. GCC+CLANG: Handling lambdas capturing class member variables, what is the correct approach?

考慮以下代碼段看起來非常無辜:

#include <functional>
#include <iostream>
#include <list>
#include <memory>

struct foo;

std::list<std::weak_ptr<foo>> wptrs;
std::function<void()> global_func;

struct foo {
    int &a;
    foo(int &a) : a{ a } {  }
    ~foo() {
        global_func = [&] {
            wptrs.remove_if([](auto &x) { return x.expired(); });
            std::cout << "a= " << a << std::endl;
        };
    }
};

int main() {
    int a = 5;
    auto ptr = std::make_shared<foo>(a);
    wptrs.emplace_back(ptr);
    ptr = nullptr;  // object is destroyed here
    global_func();
    return 0;
}

當我第一次遇到MSVC(Visual Studio 2017)上的問題時,我正在使用TCP / IP服務器,該服務器嘗試清理連接對象的weak_ptr列表。 連接對象通過調用weak_ptr<T>::expired()來調度lambda以清除連接的weak_ptr列表。 之前我很高興,因為在使用clang-6.0 +或g ++ - 7+編譯時,一切都工作正常。 然后,我必須使用MSVC並在調用destruct時收到Read Access違規。 我很震驚,並試圖產生一個表現出同樣問題的最小例子。 上面給出了最小的例子。

最小的例子使錯誤消息清晰,似乎MSVC lambda試圖訪問this->__this->a 這種訪問序列表明MSVC不捕獲的地址a (或到參考a ),而是抓住了地址*this並獲取訪問a使用這個對象。 由於當弱引用計數變為零時, *this對象被完全解除分配,因此我有內存訪問錯誤。

顯然,MSVC方法與g ++和clang的方法完全不同。 那么,我的問題是哪個編譯器是正確的?

PS MSVC案例的簡單修復:

#include <functional>
#include <iostream>
#include <list>
#include <memory>

struct foo;

std::list<std::weak_ptr<foo>> wptrs;
std::function<void()> global_func;

struct foo {
    int &a;
    foo(int &a) : a{ a } {  }
    ~foo() {
        global_func = [a = &a] {    // capture a ptr instead
            wptrs.remove_if([](auto &x) { return x.expired(); });
            std::cout << "a= " << *a << std::endl;
        };
    }
};

int main() {
    int a = 5;
    auto ptr = std::make_shared<foo>(a);
    wptrs.emplace_back(ptr);
    ptr = nullptr;  // object is destroyed here
    global_func();
    return 0;
}

永遠不會捕獲*this成員:它們無法被顯式捕獲 ,並且使用它們隱式捕獲*this (通過引用而不管捕獲默認值 ;考慮使用[=,this]以獲得清晰度)。 所以你的第二個例子是唯一正確的方法; GCC和Clang可能一直在優化foo::a的使用,因為引用不能反彈。

暫無
暫無

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

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