簡體   English   中英

C ++ 11 lambda - 為什么我需要捕獲自動持續時間變量?

[英]C++11 lambda - why do I need to capture auto duration variables?

在捕獲'[]'部分中編寫lambda函數時,我需要僅指定自動持續時間變量,而在lambda函數中使用全局變量和靜態變量而不需要捕獲。 這是為什么? 為什么我們不能像全局變量和靜態變量一樣使用自動持續時間變量?

因為lambda定義了一個單獨的范圍:它等效於:

int global_i;

struct Lambda {
    Lambda(int captured_j) : captured_j(captured_j) {}
    void operator()(){
        // in this scope, global_i is accessible, and by capturing auto_j, we make that visible as well, but we can't see auto_i
    }

    int captured_j;
}

void foo() {
    int auto_i;
    int auto_j
    // this lambda
    [j](){}
    // is just shorthand for this:
    Lambda lambda(j);
}

lambda由編譯器轉換為函數對象(就像我的示例中的Lambda類)。 並且函數對象無法訪問在實例化函數對象的范圍內聲明的局部變量。 除非你通過將它們傳遞給構造函數來“捕獲”它們。

至於為什么編譯器沒有隱式地執行此操作,而不要求您提示它,它不能,因為它不知道您是想要按值還是通過引用捕獲。 在GC語言中,您始終通過引用捕獲,因為它無關緊要 - 只要您需要它們,您引用的對象就會保持活動狀態。

但是在C ++中,您需要管理這些對象的生命周期,如果lambda總是通過引用捕獲,那么它在聲明范圍之外幾乎是無用的(因為它將包含對已被銷毀的對象的引用)。 因此,在C ++中,您必須指定是否要按值或引用進行捕獲。 因為你必須指定它,編譯器不能只為你做。

考慮這個簡單的功能:

std::function<foo()> f()
{
    foo afoo;

    return [=](){ return afoo; };
}

int main()
{
    auto l = f();

    l();
}

如果你沒有捕獲變量afoo ,它會在lamda形成的閉包被使用之前超出范圍!

另請注意,我使用by-value capture完全出於同樣的原因:返回引用/指向局部變量的指針具有未定義的行為。

從本質上講,lambda並沒有太大的魔力; 簡單地認為它是一個匿名的仿函數。

傳統的仿函數也不知道它所包含的局部變量,你需要將它們提供給它的ctor。 像lambda這樣的匿名事物沒有可自定義的c'tor,因此您可以通過這種“[]”語法提供上下文。

或考慮一下

const float g_foo = 42.f;

struct A {
    float _bar;
    struct B {
        B() : _baz(_bar /*oops*/) {}
        float _baz;
    };
};

在A :: B的閉包中,沒有A的“_bar”概念,但g_foo會被人知道。

暫無
暫無

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

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