標籤:

C++ 為什麼 Lambda 的引用捕獲 const 變數會失敗?

int main() {
vector&&> vec;
for (size_t i = 0; i &< 10; i++) { const int m = i; auto action = [] { cout &<&< m &<&< endl; }; vec.push_back(action); } for each (auto var in vec) { var(); } system("Pause"); } //輸出是 10 個 9


原則上,當for的一次循環結束之後,m就變成了野指針,你加上const也沒有用。所以你當然會讀到9個未定義數字和一個9。


在lambda裡面存了個局部對象的引用啊。


Dangling references

If an entity is captured by reference, implicitly or explicitly, and the function call operator of the closure object is invoked after the entity"s lifetime has ended, undefined behavior occurs. The C++ closures do not extend the lifetimes of the captured references.

翻譯

野引用

如果對一個實體以引用方式捕獲,而調用閉包對象的時候已經超過了這個實體的生命周期,無論是直接捕獲還是間接捕獲,都將會造成未定義行為。C++閉包不會延長引用方式捕獲的元素的生命周期。

題主你的這個引用就是教科書級別的野引用。m的生命周期只限於for循環內,在你調用的時候已經結束。


你想要的是 static int m 吧


C11支持的只是lambda表達式而不是閉包

什麼意思呢?就是lambda只是個語法糖,用於簡寫函數指針的。所以cpp的lambda表達式有什麼卵用呢?沒有卵用。

但是話又說回來,為了支持閉包,是一定需要支持垃圾回收的。因為每次閉包內的數據都需要被「snapshot」或者說棧需要snapshot,手工回收內存會變成一場災難。而cpp的設計特點就是沒有垃圾回收。所以cpp支持不了閉包。想用這種類似閉包的東西,還是得用面向對象編程的思維,new個class出來才行。

=======

答主錯了,居然直接忽略了cpp有棧上對象和對象副本這回事。所以確實可以有閉包,且不是語法糖,而且不需要垃圾回收。


因為你沒有寫Rust


推薦閱讀:

protobuf 變長64位無符號整數 為什麼最多需要消耗10位元組而不是9位元組?
C++ type_traits里哪些東西通過標準語言沒有可能實現而必須尋求編譯器內建支持?
看完 C++ 課本能否直接上手 Qt?
C++IO標準庫 能否非入侵的修改<< >>操作符的行為?
為什麼用C或C++表達Windows COM技術那麼複雜呢?是C或C++缺少什麼嗎~

TAG:C |