簡體   English   中英

在 lambda 的捕獲中聲明的變量的類型推導

[英]Type deduction for variable declared in lambda's capture

在這個片段中,我在 lambda 的捕獲中聲明了一個變量i

int main()
{
    vector<int> vec;

    // Pushing 0-99 numbers to vector
    std::generate_n(std::back_inserter(vec), 100, [i = 0]() mutable { return i++; });

    return 0;
}

如你所見,沒有任何地方為i聲明類型。

據我所知,我可以用這種方式編寫等效的功能:

int main()
{
    vector<int> vec;

    // Pushing 0-99 numbers to vector
    std::generate_n(std::back_inserter(vec), 100, [](){
             static int i = 0; 
             return i++; });

    return 0;
}

編譯器如何知道第一個例子中i的類型? 它是從我對其執行的操作中推導出來的 (++) 嗎? 它是否知道它是int因為容器?

使用 -std=c++14 和 -std=c++17 使用 GCC 進行編譯時沒有任何抱怨。 盡管如此,如果我使用 -std=c++11 進行編譯,則會收到以下警告:

lambda_test.cpp: In function ‘int main()’:
lambda_test.cpp:24:51: warning: lambda capture initializers only available with -std=c++14 or -std=gnu++14
  std::generate_n(std::back_inserter(first), 100, [i = 0]() mutable { return i++; });
                                                   ^

更多:鑒於評論,我試圖查看編譯器為 c++11 和 14 生成的內容的差異,但它生成相同的代碼: https : //cppinsights.io/s/43411e6f

正如錯誤所說,您必須激活 C++14 才能使 lambda 捕獲初始值設定項工作,因為它是在 C++14 中添加的。

據我所知,我可以用這種方式編寫等效的功能:

不,靜態存儲在功能上是不同的。 使用捕獲,您可以復制 lambda,它將復制捕獲的狀態。 使用靜態變量,每個 lambda 訪問相同的全局變量。

編譯器如何知道第一個例子中 i 的類型? 它是從我對其執行的操作中推導出來的 (++) 嗎? 它是否知道它是 int 因為容器?

不,因為許多類型都有 ++ 運算符。

編譯器簡單地使用初始化器來推斷類型。 你可以看到它好像那里有一個隱藏的auto

std::generate_n(std::back_inserter(vec), 100, [/* auto */ i = 0]() mutable { return i++; });

文字0int類型。 所以i是一個int

從技術上講,您也可以這樣做:

std::generate_n(std::back_inserter(vec), 100, [/* auto */ i = 0ull]() mutable { return i++; });

然后iunsigned long long類型,因為文字0ull是那種類型。

它的工作原理就像你做的那樣

auto i = 0;

如果您不捕獲現有變量並且該初始化器用於確定類型,則必須指定一個初始化器。

暫無
暫無

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

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