簡體   English   中英

C ++ lambda構造函數參數可以捕獲構造的變量嗎?

[英]Can a C++ lambda constructor argument capture the constructed variable?

以下編譯 但是,有沒有任何懸掛參考問題?

    class Foo {
         Foo(std::function<void(int)> fn) { /* etc */ }
    }

    void f(int i, Foo& foo) { /* stuff with i and foo */ }

    Foo foo([&foo](int i){f(i, foo);});

似乎工作。 (真正的lambda當然更復雜。)

但是,有沒有任何懸掛參考問題?

這完全取決於你對Foo所作所為。 下面是必須懸掛引用問題的例子:

struct Foo {
     Foo() = default;
     Foo(std::function<void(int)> fn) : fn(fn) { }
     std::function<void(int)> fn;
}

Foo outer;
{
    Foo inner([&inner](int i){f(i, inner);});
    outer = inner;
}
outer.fn(42); // still has reference to inner, which has now been destroyed

lambda表達式[&foo](int i){f(i, foo);}將導致編譯器生成類似這樣的閉包類(但不完全正確):

class _lambda
{
    Foo& mFoo; // foo is captured by reference

public:
    _lambda(Foo& foo) : mFoo(foo) {}

    void operator()(int i) const
    {
       f(i, mFoo);
    }
};

因此,聲明Foo foo([&foo](int i){f(i, foo);}); 被視為Foo foo(_lambda(foo)); 在構造時捕獲foo本身在這種情況下沒有問題,因為這里只需要它的地址(引用通常通過指針實現)。

類型std::function<void(int)>將在內部復制構造此lambda類型,這意味着Foo的構造函數參數fn包含_lambda對象的副本(其中包含對foo的引用(即mFoo))。

這些暗示在某些情況下可能會出現懸掛參考問題,例如:

std::vector<std::function<void(int)>> vfn; // assume vfn live longer than foo

class Foo {
     Foo(std::function<void(int)> fn) { vfn.push_back(fn); }
}

void f(int i, Foo& foo) { /* stuff with i and foo */ }

Foo foo([&foo](int i){f(i, foo);});

....

void ff()
{
    // assume foo is destroyed already,
    vfn.pop_back()(0); // then this passes a dangling reference to f.
}

暫無
暫無

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

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