私はこのようなことをしようとしています:
for ( std::list< Cursor::Enum >::reverse_iterator i = m_CursorStack.rbegin(); i != m_CursorStack.rend(); ++i )
{
if ( *i == pCursor )
{
m_CursorStack.erase( i );
break;
}
}
ただし、消去には逆反復子ではなく反復子が必要です。逆反復子を通常の反復子に変換する方法や、この要素をリストから削除する別の方法はありますか?
さらに調査とテストを行った結果、解決策が見つかりました。どうやら標準[24.4.1/1]によれば、i.base()とiの関係は次のとおりです。
&*(reverse_iterator(i)) == &*(i - 1)
(から ドブス博士の記事 ):
そのため、base()を取得するときにオフセットを適用する必要があります。したがって、解決策は次のとおりです。
m_CursorStack.erase( --(i.base()) );
[〜#〜] edit [〜#〜]
C++ 11用の更新。
reverse_iterator i
は変更されていません:
m_CursorStack.erase( std::next(i).base() );
reverse_iterator i
は高度です:
std::advance(i, 1);
m_CursorStack.erase( i.base() );
これは以前のソリューションよりもはるかに明確です。必要なものを使用してください。
m_CursorStack.erase( (++i).base())
はiの値を変更するため、for
ループ(元の質問を参照)で使用すると問題になる可能性があることに注意してください。正しい式はm_CursorStack.erase((i+1).base())
です
...またはリストからこの要素を削除する別の方法?
これには-std=c++11
フラグが必要です(auto
の場合):
auto it=vt.end();
while (it>vt.begin())
{
it--;
if (*it == pCursor) //{ delete *it;
it = vt.erase(it); //}
}
ここで_reverse_iterator
_のbase()
メソッドを使用して結果をデクリメントすると、_reverse_iterator
_ sには通常のiterator
sと同じステータスが与えられないことに注意する価値があります。通常、このような理由から、通常のiterator
sを_reverse_iterator
_ s(および_const_iterator
_ sおよび_const_reverse_iterator
_ s)よりも優先する必要があります。理由の詳細な議論については Doctor Dobbs 'Journal をご覧ください。
typedef std::map<size_t, some_class*> TMap;
TMap Map;
.......
for( TMap::const_reverse_iterator It = Map.rbegin(), end = Map.rend(); It != end; It++ )
{
TMap::const_iterator Obsolete = It.base(); // conversion into const_iterator
It++;
Map.erase( Obsolete );
It--;
}
進行中にすべてを消去する必要がない場合は、問題を解決するために、erase-removeイディオムを使用できます。
_m_CursorStack.erase(std::remove(m_CursorStack.begin(), m_CursorStack.end(), pCursor), m_CursorStack.end());
_
_std::remove
_は、pCursor
に一致するコンテナ内のすべてのアイテムを最後に交換し、最初の一致するアイテムに反復子を返します。次に、範囲を使用するerase
は、最初の一致から消去され、最後に移動します。一致しない要素の順序は保持されます。
_std::vector
_を使用している場合は、コンテンツの途中での消去に大量のコピーや移動が必要になる可能性があるため、これはより速く動作する可能性があります。
または、上記のreverse_iterator::base()
の使用を説明する答えは興味深いものであり、知る価値があります。述べられている正確な問題を解決するには、_std::remove
_の方が適していると思います。
面白いことに、このページにはまだ正しい解決策がありません。したがって、以下は正しいものです。
前方反復子の場合、解決策は簡単です。
std::list< int >::iterator i = myList.begin();
while ( ; i != myList.end(); ) {
if ( *i == to_delete ) {
i = myList.erase( i );
} else {
++i;
}
}
逆反復子の場合、同じことをする必要があります。
std::list< int >::reverse_iterator i = myList.rbegin();
while ( ; i != myList.rend(); ) {
if ( *i == to_delete ) {
i = decltype(i)(myList.erase( std::next(i).base() ));
} else {
++i;
}
}
ノート:
reverse_iterator
を構築できますstd::list::erase
の戻り値を使用できますそして、以下は、消去の結果を逆イテレータに変換して、コンテナ内の要素を消去し、逆に繰り返し処理するためのコードです。少し奇妙ですが、最初または最後の要素を消去する場合でも動作します:
std::set<int> set{1,2,3,4,5};
for (auto itr = set.rbegin(); itr != set.rend(); )
{
if (*itr == 3)
{
auto it = set.erase(--itr.base());
itr = std::reverse_iterator(it);
}
else
++itr;
}
他の答えを補完するために、私はこの質問につまずいたので、あまり成功せずにstd :: stringについて検索したので、std :: string、std :: string :: eraseおよびstd :: reverse_iteratorを使用して応答します
私の問題は、完全なファイル名文字列から画像ファイル名を消去することでした。それはもともとstd :: string :: find_last_ofで解決されましたが、私はstd :: reverse_iteratorで別の方法を研究しています。
std::string haystack("\\\\UNC\\complete\\file\\path.exe");
auto&& it = std::find_if( std::rbegin(haystack), std::rend(haystack), []( char ch){ return ch == '\\'; } );
auto&& it2 = std::string::iterator( std::begin( haystack ) + std::distance(it, std::rend(haystack)) );
haystack.erase(it2, std::end(haystack));
std::cout << haystack; ////// prints: '\\UNC\complete\file\'
これは、アルゴリズム、イテレータ、および文字列ヘッダーを使用します。
何かを明確にしたかっただけです。上記のコメントと回答のいくつかでは、消去用のポータブルバージョンは(++ i).base()として言及されています。ただし、何か不足している場合を除き、正しいステートメントは(++ ri).base()です。つまり、reverse_iterator(イテレーターではなく)を「インクリメント」します。
昨日、似たようなことをする必要が生じたので、この投稿は役に立ちました。みんな、ありがとう。