簡體   English   中英

為什么這個 lambda 不會通過引用通過刪除的構造函數來捕獲這個變量?

[英]Why won't this lambda capture this variable with a deleted constructor by reference?

我的編譯器 Visual Studio 19 顯示“正在嘗試引用已刪除的函數”:

class AClass 
{public:
    AClass(const AClass& other) = delete;
    AClass() {}
    AClass(AClass&& other) { }
    AClass& operator=(const AClass& other) = delete;
    AClass& operator=(AClass&& other) { return *this; }
    int member;
};


void main()
{
    AClass a;
    AClass& aRef = a;

    [=]() { return aRef.member; }; // "Attempting to reference a deleted function"

}

我假設它正在嘗試調用已刪除的復制構造函數,但我不明白為什么,因為我試圖通過 [=] 值通過引用捕獲,這意味着我不復制對象 AClass,我不看看如何涉及任何副本。 我的理解是 lambda 看起來像這樣:

struct lambda {
    AClass& refToAClass; // <--- this is the captured object
    lambda(AClass& captureVariable) : refToAClass(captureVariable) {}
    int operator()() const
    {
        return refToAClass.member;
    }
};


void main()
{
      // AND I CAN CONSTRUCT THE LAMBDA, NO COPYING OF AClass INVOLVED
      AClass a;
      AClass& aRef = a;

      lambda lam(aRef); // WORKS FINE
}

本案如何涉及副本? 我如何捕獲該參考?

標准

對於 copy 捕獲的每個實體,在閉包類型中聲明了一個未命名的非靜態數據成員。 這些成員的聲明順序未指定。 如果實體是對對象的引用,則此類數據成員的類型被引用類型,如果實體是對函數的引用,則是對被引用函數類型的左值引用,否則是對應的捕獲實體的類型 匿名工會的成員不得被復制。

cpprefence措辭更好:

每個數據成員的類型是對應的捕獲實體的類型,除非實體具有引用類型(在這種情況下,對函數的引用被捕獲為對被引用函數的左值引用,而對對象的引用被捕獲為引用的對象)。

也許這有助於澄清我認為你對什么感到困惑:

template <typename T> void f(T arg) { }

int x = 10;
int& r = x;

auto y = r;     // y is int (copied value from reference)
f(r);           // T in f<T>() is deduced to int, arg in f() is int

在這兩種情況下,如果您希望結果作為參考,則必須這樣說:

template <typename T> void f(T& arg) { }

int x = 10;
int& r = x;

auto& y = r;     // y is reference-to-int
f(r);            // T in f<T>() is int, arg in f is ref-to-int

同樣,在您的代碼中:

AClass a;
AClass& aRef = a;

[=]() { return aRef.member; }; // "Attempting to reference a deleted function"

捕獲的 aRef 是嘗試從對不同對象的引用復制局部變量。 使用 [=] 表示按值復制,它不會將其讀作“哦,源是引用,所以我將按值復制引用並將引用存儲在引用中。” 它實際上說,“如果源類型有引用限定符,忽略 並考慮剩下的。你想按值復制嗎?好的,我將一個 AClass 復制到一個新變量中。哦等等......不能。抱歉.”

你想要的是:

[&]() { return aRef.member; };

或者更具體地說:

[&aRef]() { return aRef.member; };

這告訴捕獲的類型它應該是一個引用。 在這種情況下,源類型不如目標類型重要。

暫無
暫無

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

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