ラムダ式の「mutable」について – プログラミング – Home

ラムダ式の「mutable」について
 
通知
すべてクリア

[解決済] ラムダ式の「mutable」について


山川
 山川
(@山川)
ゲスト
結合: 12年前
投稿: 2
Topic starter  

最近、C++の新しい機能について勉強しているのですが、
タイトルの件についてよく理解できない挙動があります。

以下の擬似コードについて
-----------------
int i, count = 0;
list<int> vt;
list<int>::iterator itr, last;

for (i = 0; i < 10; ++i) vt.push_back(i);

for (itr = vt.begin(); itr != vt.end(); ++itr) wcout << *itr << L, ;
wcout << endl;

last = remove_if(vt.begin(), vt.end(),
[count] (int n) mutable { return ++count == 5; });

vt.erase(last, vt.end());

for (itr = vt.begin(); itr != vt.end(); ++itr) wcout << *itr << L, ;
wcout << endl;
-----------------

私として、5番目の要素を削除する意図があるのですが、
実際に出力される結果は以下のとおりです。

0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 5, 6, 7, 8,

「4」に加えて「9」まで削除されてしまいます。
これはなぜなのでしょうか?

ちなみに、mutableを使用せずに、以下のような参照形式にすると期待通りの
結果になります。

last = remove_if(vt.begin(), vt.end(),
[&count] (int n) { return ++count == 5; });

「mutable」と「参照形式」によるキャプチャーでは何が違うのでしょうか?


引用未解決
トピックタグ
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

この現象に関して言うなら lambda は無関係だ。
提示の *理解困難な挙動* の原因は remove_if のほうにある。

上記のコードが「プログラマの勝手な期待通り」に動くには、
アルゴリズム関数内で関数オブジェクトがコピーされてはならないわけだ。
それは迷信。
http://www.kijineko.co.jp/tech/superstitions/functor-is-not-copied-in-
algorithm.html

[&] の場合は、値が変更されるのは元の count であるから、
lambda 関数オブジェクトがコピーされても、されなくても、結果は同じ。
[=] の場合は、関数オブジェクトの初期化の際に
lambda 内部に count のコピーである別の変数が作られる。
値が変更されるのはそのコピーされた別の変数 (初期値 count) であるわけだ。
remove_if 中に関数オブジェクトがコピーされると [&] とは違う結果になる。


返信引用
山川
 山川
(@山川)
ゲスト
結合: 12年前
投稿: 2
Topic starter  

ラムダ式のオブジェクトがコピーされていたんですね。
理由が分かって安心しました。

アドバイスありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました