역 반복자를 사용하여 지우기를 호출하는 방법
나는 이런 식으로하려고합니다.
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()) );
편집하다
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())
A의 사용하는 경우 문제가 될 수 for
는 i 값을 변경하기 때문에 (원래의 질문 참조) 루프를. 올바른 표현은m_CursorStack.erase((i+1).base())
... 또는이 요소를 목록에서 제거하는 다른 방법은 무엇입니까?
이 -std=c++11
플래그에는 (for 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
에서 const_iterator
s 및 const_reverse_iterator
s 및 s 를 선호해야합니다 . 이유에 대한 자세한 내용은 Dr 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--;
}
진행하면서 모든 것을 지울 필요가 없다면 문제를 해결하기 위해 지우기-삭제 관용구를 사용할 수 있습니다.
m_CursorStack.erase(std::remove(m_CursorStack.begin(), m_CursorStack.end(), pCursor), m_CursorStack.end());
std::remove
swaps all the items in the container that match pCursor
to the end, and returns an iterator to the first match item. Then, the erase
using a range will erase from the first match, and go to the end. The order of the non-matching elements is preserved.
This might work out faster for you if you're using a std::vector
, where erasing in the middle of the contents can involve a lot of copying or moving.
Or course, the answers above explaining the use of reverse_iterator::base()
are interesting and worth knowing, to solve the exact problem stated, I'd argue that std::remove
is a better fit.
And here is the piece of code to convert the result of erase back to a reverse iterator in order to erase an element in a container while iterating in the reverse. A bit strange, but it works even when erasing the first or last element:
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;
}
Funny that there is no correct solution on this page yet. So, the following is the correct one:
In case of the forward iterator the solution is straight forward:
std::list< int >::iterator i = myList.begin();
while ( ; i != myList.end(); ) {
if ( *i == to_delete ) {
i = myList.erase( i );
} else {
++i;
}
}
In case of reverse iterator you need to do the same:
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;
}
}
Notes:
- You can construct a
reverse_iterator
from an iterator - You can use the return value of
std::list::erase
Just wanted to clarify something: In some of the above comments and answers the portable version for erase is mentioned as (++i).base(). However unless I am missing something the correct statement is (++ri).base(), meaning you 'increment' the reverse_iterator (not the iterator).
나는 어제 비슷한 일을 할 필요가 있었고이 게시물이 도움이되었습니다. 모두 감사합니다.
다른 답변을 보완하고 많은 성공없이 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\'
알고리즘, 반복자 및 문자열 헤더를 사용합니다.
참고 URL : https://stackoverflow.com/questions/1830158/how-to-call-erase-with-a-reverse-iterator
'Programing' 카테고리의 다른 글
파이썬 'for'루프에서 범위 지정 (0) | 2020.06.06 |
---|---|
git 저장소에 여러 프로젝트를 배치하는 가장 좋은 방법은 무엇입니까? (0) | 2020.06.06 |
파이썬에서 객체의 복사본을 어떻게 만들 수 있습니까? (0) | 2020.06.06 |
캐시 없음과 재확인의 차이점 (0) | 2020.06.06 |
virtualenv에 해당하는 루비? (0) | 2020.06.06 |