首頁 >後端開發 >C++ >C 11 Lambda 能否在不呼叫未定義行為的情況下捕獲引用?

C 11 Lambda 能否在不呼叫未定義行為的情況下捕獲引用?

Susan Sarandon
Susan Sarandon原創
2024-11-04 22:03:02681瀏覽

Can C  11 Lambdas Capture References Without Invoking Undefined Behavior?

在 C 11 Lambda 中捕獲引用

在 C 中,lambda 表達式可以從其封閉範圍捕獲變數。然而,捕獲的方法決定了變數是透過引用還是透過值來存取。考慮以下程式碼:

<code class="cpp">#include <functional>
#include <iostream>

std::function<void()> make_function(int& x) {
    return [&]{ std::cout << x << std::endl; };
}

int main() {
    int i = 3;
    auto f = make_function(i);
    i = 5;
    f();
}</code>

此程式碼使用 [&] 語法透過引用擷取變數 x。問題是這個程式是否保證在不呼叫未定義行為的情況下輸出 5。

答案:是

程式碼保證正確運作。在檢查底層標準措詞之前,重要的是要注意此代碼的功能符合 C 委員會的預期。然而,C 11 標準的最初措辭在這一問題上並不清楚,導致 CWG 問題 2011 被提出來提供澄清。這個問題正在C標準的持續開發中解決。

標準解釋

根據C標準的[expr.prim.lambda]/17,只有引用複製捕獲的實體的id 表達式才會轉換為lambda 閉包類型的成員存取。引用透過引用捕獲的實體的 id 表達式將被保留,並繼續表示它們在封閉範圍中表示的相同實體。

在上面的程式碼中,捕獲的實體是 make_function 函數的參數 x ,落在 lambda 的可達範圍內。因此,lambda 表達式中的引用 x 引用了在 main 函數中宣告的原始變數。

在 make_function 函數傳回後,在 x 的生命週期之外引用 x 最初可能會出現問題。但是,在有限的情況下,可以在引用的生命週期之外對其進行引用。一般來說,引用要麼在作用域中聲明,要麼是類別成員,在這種情況下,類別本身必須在其生命週期中。

因此,標準沒有明確禁止在其生命週期之外使用引用。此漏洞允許支援在 lambda 表達式中透過引用捕獲引用。

CWG 2012 期問題與未來澄清

提出CWG 2012 期問題是為了解決監督問題在某些情況下,引用可以在其生命週期之外被引用。此問題的解決無意中影響了透過引用引用捕獲 lambda 的規範。不過,預計此回歸將在 C 17 發布之前修復。

以上是C 11 Lambda 能否在不呼叫未定義行為的情況下捕獲引用?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn