<질문>
나는 다음과 같은 것을 시도하고 있습니다.
for ( std::list< Cursor::Enum >::reverse_iterator i = m_CursorStack.rbegin(); i != m_CursorStack.rend(); ++i )
{
if ( *i == pCursor )
{
m_CursorStack.erase( i );
break;
}
}
그러나 erase는 역방향 반복자가 아닌 반복기를 사용합니다. 역방향 반복기를 일반 반복기로 변환하는 방법 또는 목록에서이 요소를 제거하는 다른 방법이 있습니까?
<답변1>
더 많은 연구와 테스트를 거쳐 해결책을 찾았습니다. 표준 [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() );
이전 솔루션보다 훨씬 명확합니다. 필요한 것을 사용하십시오.
<답변2>
m_CursorStack.erase ((++ i) .base ())는 i의 값을 변경하기 때문에 for 루프 (원래 질문 참조)에서 사용하는 경우 문제가 될 수 있습니다. 올바른 표현은 m_CursorStack.erase ((i + 1) .base ())입니다.
<답변3>
... 또는 목록에서이 요소를 제거하는 다른 방법?
여기에는 -std = c ++ 11 플래그 (자동의 경우)가 필요합니다.
auto it=vt.end();
while (it>vt.begin())
{
it--;
if (*it == pCursor) //{ delete *it;
it = vt.erase(it); //}
}
<답변4>
아직이 페이지에 올바른 해결책이 없다는 것이 재밌습니다. 따라서 다음은 올바른 것입니다.
순방향 반복자의 경우 솔루션은 간단합니다.
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의 반환 값을 사용할 수 있습니다.
<답변5>
reverse_iterator의 base () 메서드를 사용하고 결과를 줄이는 것이 여기서 작동하지만 reverse_iterator가 일반 반복자와 동일한 상태를 갖지 않는다는 점에 주목할 가치가 있습니다. 일반적으로, 정확히 이와 같은 이유로 reverse_iterators (const_iterators 및 const_reverse_iterators뿐만 아니라)보다 일반 반복기를 선호해야합니다. 이유에 대한 심도있는 논의는 Doctor Dobbs의 저널을 참조하십시오.
<답변6>
typedef std::map 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--;
}
<답변7>
그리고 여기에 역방향으로 반복하는 동안 컨테이너의 요소를 삭제하기 위해 삭제 결과를 역방향 반복기로 변환하는 코드가 있습니다. 약간 이상하지만 첫 번째 또는 마지막 요소를 지울 때도 작동합니다.
std::set 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;
}
<답변8>
진행하면서 모든 것을 지울 필요가 없다면 문제를 해결하기 위해 erase-remove 관용구를 사용할 수 있습니다.
m_CursorStack.erase(std::remove(m_CursorStack.begin(), m_CursorStack.end(), pCursor), m_CursorStack.end());
std :: remove는 pCursor와 일치하는 컨테이너의 모든 항목을 끝까지 교체하고 첫 번째 일치 항목에 대한 반복자를 반환합니다. 그런 다음 범위를 사용하여 지우기는 첫 번째 일치에서 지워지고 끝으로 이동합니다. 일치하지 않는 요소의 순서는 유지됩니다.
std :: vector를 사용하는 경우이 작업이 더 빨리 처리 될 수 있습니다. 여기서 내용 중간에있는 지우기에는 많은 복사 또는 이동이 포함될 수 있습니다.
또는 물론 reverse_iterator :: base () 사용을 설명하는 위의 답변은 흥미롭고 알 가치가 있으며, 명시된 문제를 정확히 해결하기 위해 std :: remove가 더 적합하다고 주장합니다.
<답변9>
뭔가를 명확히하고 싶었습니다. 위의 주석과 답변 중 일부에서 지우기를위한 휴대용 버전은 (++ i) .base ()로 언급되었습니다. 그러나 내가 뭔가를 놓치지 않는 한 올바른 진술은 (++ ri) .base ()입니다. 이는 reverse_iterator (반복자가 아님)를 '증가'한다는 것을 의미합니다.
어제 비슷한 일을해야 할 필요가 생겼는데이 게시물이 도움이되었습니다. 모두 감사합니다.
<답변10>
다른 사람의 답변을 보완하기 위해 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\'
이것은 알고리즘, 반복기 및 문자열 헤더를 사용합니다.
<답변11>
역 반복기는 사용하기 매우 어렵습니다. 그래서 그냥 일반 반복자를 사용했습니다. 'r'마지막 요소부터 시작합니다. 지울 것을 찾을 때. 지우고 다음 반복자를 반환합니다. 예를 들어 세 번째 요소를 삭제하면 현재 네 번째 요소를 가리 킵니다. 그리고 새로운 3rd. 따라서 왼쪽으로 이동하려면 1을 줄여야합니다.
void remchar(string& s,char c)
{
auto r = s.end() - 1;
while (r >= s.begin() && *r == c)
{
r = s.erase(r);
r -= 1;
}
}
'개발 > C++' 카테고리의 다른 글
C ++에서 int를 문자열로 변환하는 가장 쉬운 방법 (0) | 2020.09.30 |
---|---|
STL 또는 Qt 컨테이너? (0) | 2020.09.30 |
if… else if 문을 확률로 정렬하면 어떤 효과가 있습니까? (0) | 2020.09.30 |
보호 또는 개인 생성자 만있는 클래스에서 :: std :: make_shared를 어떻게 호출합니까? (0) | 2020.09.30 |