わかりました、私はここで愚かな間違いを犯したと思います。 DisplayDevice3dのリストがあり、各DisplayDevice3dにはDisplayMode3dのリストが含まれています。 DisplayMode3dを持たないDisplayDevice3dのリストからすべてのアイテムを削除したい。私はそれを行うためにラムダを使用しようとしています、すなわち:
// If the device doesn't have any modes, remove it.
std::remove_if(MyDisplayDevices.begin(), MyDisplayDevices.end(),
[](DisplayDevice3d& device)
{
return device.Modes.size() == 0;
}
);
MyDisplayDevicesの6つのDisplayMode3dのうち、ModesコレクションにDisplayMode3dがあるのは1つだけですが、リストからは何も削除されていません。
私はここでどのようなミスを犯しましたか?
編集:
ああ、私の間違いは、std :: remove_ifの代わりにMyDisplayDevices.remove_ifを使用しなければならないことでしたが、以下の回答はstd :: remove_if:pの使用に適しています。
MyDisplayDevices.remove_if( [](DisplayDevice3d const & device)
{
return device.Modes.size() == 0;
});
Remove_ifから返されたイテレータでeraseを呼び出す必要があります。次のようになります。
auto new_end = std::remove_if(MyDisplayDevices.begin(), MyDisplayDevices.end(),
[](const DisplayDevice3d& device)
{ return device.Modes.size() == 0; });
MyDisplayDevices.erase(new_end, MyDisplayDevices.end());
remove_if
はリストから何も削除せず、単に最後に移動します。 erase
とともに使用する必要があります。詳細は question をご覧ください。
他の人が言及したように、それを機能させる方法があります。しかし、私のアドバイスは_remove_if
_を完全に避け、代わりに標準のイテレータベースの削除に固執することです。以下のイディオムは、list
とvector
の両方で機能し、予期しない動作を引き起こしません。
_for( vector<TYPE>::iterator iter = vec.begin() ; iter != vec.end() ; )
if( iter->shouldRemove )
iter = vec.erase( iter ) ; // advances iter
else
++iter ; // don't remove
_
以下のコメントが言及しているように、このメソッドは複数の要素が削除されたとき_remove_if
_よりもコストが高くなります。
_remove_if
_は、ベクトルのさらに前方から要素をコピーし、ベクトルの直前のベクトルによってベクトルから削除する必要があるベクトルを上書きすることで機能します。例:ベクトルでremove_ifを呼び出して、0個の要素をすべて削除します。
_0 1 1 0 1 0
_
結果:
_1 1 1 0 1 0
_
ベクトルがまだ正しくないことに注意してください。これは、_remove_if
_が最後の有効な要素へのイテレータを返すためです...ベクトルのサイズを自動的に変更しません。 _remove_if
_への呼び出しから返されたイテレータでv.erase()
を呼び出す必要があります。
以下に例を示します
_#include <stdio.h>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
void print( vector<int> &v )
{
for( int i : v )
printf( "%d ", i );
puts("");
}
int main()
{
vector<int> v = { 0, 1, 1, 0, 1, 0 };
print( v ); // 0 1 1 0 1 0
vector<int>::iterator it = remove_if( v.begin(), v.end(), [](int i){ return i == 0; } );
print( v ); // 1 1 1 0 1 0
v.erase( it, v.end() ); // actually cut out values not wanted in vector
print( v ); // 1 1 1 (correct)
}
_