在 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中文網其他相關文章!