Estou tentando fazer algo assim:
for ( std::list< Cursor::Enum >::reverse_iterator i = m_CursorStack.rbegin(); i != m_CursorStack.rend(); ++i )
{
if ( *i == pCursor )
{
m_CursorStack.erase( i );
break;
}
}
No entanto, apagar exige um iterador e não um iterador reverso. existe uma maneira de converter um iterador reverso em um iterador regular ou outra maneira de remover esse elemento da lista?
i != m_CursorStack.rend()
. Em vez disso, escrevai = m_CursorStack.rbegin(), end = m_CursorStack.rend(); i != end;
. Ou seja, inicialize um iterador que você pode manter para comparação repetida - supondo que a posição final não seja alterada como efeito colateral do seu corpo em loop.std::remove
?Respostas:
Depois de mais algumas pesquisas e testes, encontrei a solução. Aparentemente, de acordo com o padrão [24.4.1 / 1], a relação entre i.base () ei é:
(de um artigo do Dr. Dobbs ):
Portanto, você precisa aplicar um deslocamento ao obter a base (). Portanto, a solução é:
EDITAR
Atualizando para C ++ 11.
reverse_iterator
i
permanece inalterado:reverse_iterator
i
é avançado:Acho isso muito mais claro que minha solução anterior. Use o que você precisar.
fonte
m_CursorStack.erase( (++i).base())
(cara, fazer essas coisas com iteradores reversos faz minha cabeça doer ...). Também deve ser observado que o artigo DDJ é incorporado ao livro "Effective STL" de Meyer.*
utilizasse, mas estamos falando sobre qual elemento você apontaria se os utilizassebase
, que é um elemento à direita. Não sou muito fã das soluções--(i.base())
ou(++i).base()
, pois elas modificam o iterador. Eu prefiro o(i+1).base()
que funciona também.Observe que
m_CursorStack.erase( (++i).base())
pode ser um problema se usado em umfor
loop (consulte a pergunta original), pois altera o valor de i. A expressão correta ém_CursorStack.erase((i+1).base())
fonte
iterator j = i ; ++j
, porquei+1
não funciona em um iterador, mas essa é a idéia certam_CursorStack.erase(boost::next(i).base())
Boost. ou em C ++ 11m_CursorStack.erase(std::next(i).base())
Isso requer o
-std=c++11
sinalizador (paraauto
):fonte
Engraçado que ainda não há uma solução correta nesta página. Portanto, o seguinte é o correto:
No caso do iterador direto, a solução é direta:
No caso do iterador reverso, você precisa fazer o mesmo:
Notas:
reverse_iterator
partir de um iteradorstd::list::erase
fonte
Enquanto estiver usando o
reverse_iterator
'sbase()
método e diminuindo o resultado funciona aqui, é importante notar quereverse_iterator
s não é dado o mesmo estatuto que regularesiterator
s. Em geral, você deve prefeririterator
s regulares parareverse_iterator
s (e também paraconst_iterator
es econst_reverse_iterator
s), por motivos precisos como este. Veja o Diário do Doutor Dobbs para uma discussão aprofundada sobre o porquê.fonte
fonte
E aqui está o trecho de código para converter o resultado de apagar novamente em um iterador reverso, a fim de apagar um elemento em um contêiner enquanto itera no reverso. Um pouco estranho, mas funciona mesmo ao apagar o primeiro ou o último elemento:
fonte
Se você não precisar apagar tudo à medida que avança, para resolver o problema, use o idioma apagar-remover:
std::remove
troca todos os itens no contêiner que correspondempCursor
ao final e retorna um iterador para o primeiro item de correspondência. Então oerase
uso de um intervalo será apagado da primeira partida e chegará ao fim. A ordem dos elementos não correspondentes é preservada.Isso pode funcionar mais rápido se você estiver usando um
std::vector
, onde a exclusão no meio do conteúdo pode envolver muitas cópias ou movimentação.Ou, é claro, as respostas acima que explicam o uso de
reverse_iterator::base()
são interessantes e vale a pena conhecer, para resolver o problema exato declarado, eu argumentaria questd::remove
é um ajuste melhor.fonte
Só queria esclarecer uma coisa: Em alguns dos comentários e respostas acima, a versão portátil para apagar é mencionada como (++ i) .base (). No entanto, a menos que esteja faltando alguma coisa, a instrução correta é (++ ri) .base (), significando que você 'incrementa' o reverse_iterator (não o iterador).
Encontrei ontem uma necessidade de fazer algo semelhante e este post foi útil. Obrigado a todos.
fonte
Para complementar as respostas de outras pessoas e porque eu me deparei com essa pergunta enquanto pesquisava sobre std :: string sem muito sucesso, aqui vai uma resposta com o uso de std :: string, std :: string :: erase e std :: reverse_iterator
Meu problema foi apagar o nome de arquivo de uma imagem de uma string de nome de arquivo completa. Foi originalmente resolvido com std :: string :: find_last_of, mas eu pesquiso uma maneira alternativa com std :: reverse_iterator.
Isso usa algoritmos, iteradores e cabeçalhos de string.
fonte
O iterador reverso é bastante difícil de usar. Então, apenas usei o iterador geral. 'r' Começa do último elemento. Quando encontrar algo para apagar. apague-o e retorne o próximo iterador. por exemplo, quando excluir o terceiro elemento, ele apontará o quarto elemento atual. e novo terceiro. Portanto, deve ser diminuído 1 para mover para a esquerda
fonte