Re: [問題] lambda capture list 的問題

作者: LPH66 (-6.2598534e+18f)   2016-10-30 06:53:00
你應該有一個概念沒有搞懂:
C++ 的 lambda 其實是個 functor
在你寫 lambda 的當下有一個 class 在此成立, 並產生一個實體
lambda 函式內容則是此 class 的 operator () 內容
這個 operator () 預設是有常數性, 也就是在函式中這 lambda class 是當做常數
(其實跟平常 class 宣告裡在 member function 宣告後面加上 const 的意思一模一樣
之所以這麼設定的理由可見這連結 http://stackoverflow.com/questions/5501959/ )
所有被 capture by value 的變數都是這個 class 的成員變數
在 lambda 產生的當下產生實體時會複製進去
※ 引述《dreamboat66 (小嫩)》之銘言:
: 寫程式遇到一個compile error原本看不出來原因
: 簡化一下問題如下
: http://ideone.com/9Vqbvu
: 如果真的遇到這種case
: 我要很大方的冠上mutable嗎?
: 還是想辦法裡面const cast拿掉const讓move成功
所以在這裡, 裡面的 f2 和外面的 f2 是不同的變數
@@@+ 和 @@@- 之間的那次複製就是複製出裡面的 f2 的那次
因此兩個 f2 既然沒關係, 使用 move 也就沒有意義了
move 沒有用的原因確實是常數性沒錯
但這是因為這個 operator () 的常數性, 使得其成員物件全部都是 const
這裡如果你要把外面的 f2 給 move 進來的話
可以使用下面的 C++14 的帶初始化 capture, 寫 [f2 = move(f2)](...){...}
這樣在建構時就會把外面的 f2 給 move 進去
: 如果慣上mutable的話
: http://ideone.com/s5KtOq
: 又遇到奇怪問題
: 為什麼他要保留const 這屬性, 如果alias他名字(這好像c++14才能這樣寫?)就不會...
: 這有什麼特殊含意嗎? 因為用template 推型別的觀念 const是不會保留的呀
: 以上
: 謝謝
所以這裡也不是 alias
而是這個 lambda class 裡的兩個成員變數 f2 和 f3, 都由外面的 f2 複製而來
這個 f3(f2) 是當做有個 auto f3(f2); 卡在這 lambda 宣告之前
但不在外面的 scope 裡
所以後一個指向 f3(f2) 的 error 就是因為這個 f2 是外面的 f2, 那是 const
但你卻宣告了 (lvalue-)copy ctor 為 explicit
不過這個先不管, 你的問題是在 Bar(f3) 和 Bar(f2) 的差別
f3 跟 f2 的差別在於 f2 繼承自它抓取的變數的常數性, 但 f3 卻是一個全新的變數
下面這個連結應該回答了你這部份的問題
http://stackoverflow.com/questions/31485041/
解法裡面也提到了, 既然你有 C++14 的帶初始化 capture
寫 [f2 = f2] 就好, 這樣如上所言這裡就會用上 auto 的規則, 常數性就不見了
或是你還想要把外面的 f2 給 move 進來那就一樣 [f2 = move(f2)]
作者: dreamboat66 (小嫩)   2016-10-30 10:39:00
謝謝解答, 因為我的平台不能用c++14 所以才想問這些"f2 繼承自它抓取的變數的常數性" 這是規則嗎?回個問 整理一下問題 謝謝

Links booklink

Contact Us: admin [ a t ] ucptt.com