Indexof de estilo Arraylist para std :: vetor em c ++?
Pergunta
Estou entrando no C ++ da Java e tenho uma situação de design comum em que tenho um elemento (um não primitivo) que gostaria de remover de um vetor de std ::.
Em Java, eu escrevia algo como: ArrayList.remove (ArrayList.indexof (myclassInstance));
Em C ++, com um vetor STD ::, qual é a melhor maneira / mais performante / mais limpa de fazer isso?
A melhor coisa que consigo pensar é criar uma referência à instância que estou procurando e depois itera através do vetor até encontrar essa referência. Essencialmente, para comparar o endereço de memória de cada elemento no vetor com a referência até que eu receba uma correspondência.
Estou no caminho certo? Ou existe uma maneira melhor de fazer isso? (Talvez usando um contêiner DST diferente, eu só usei STD :: Vector até agora.)
Solução
#include <algorithm>
std::vector<Foo>::iterator it = std::find(vec.begin(), vec.end(), foo_2b_found);
if (it != vec.end()) vec.erase(it);
Outras dicas
Usar std::find
para encontrar o elemento e vector::erase
para removê -lo.
std::find
essencialmente itera através do vetor para encontrar o elemento, e você não pode fazer melhor com um vetor simples (o mesmo é o caso do Java's ArrayList
). Se você deve ou não usar um contêiner diferente depende de seus requisitos.
Se você quiser pesquisar linearmente através do vetor, então
seq.erase( std::find( seq.begin(), seq.end(), elt ));
Se você tem um predicado e deseja remover todos os itens que correspondem ao predicado, então:
seq.erase( std::remove_if( seq.begin(), seq.end(), Pred ), seq.end());
Nenhum desses métodos é a maneira mais com desempenho, porque eles exigem pesquisa linear e, mesmo que seu elemento seja encontrado desde o início, a apagação é cara porque precisa mover todos os outros elementos por posição para mantê -los contíguos.
O uso da lista STD :: abordaria o último deles: a pesquisa seria linear, mas a apagamento seria tempo constante.
Se for possível armazenar seus elementos em um contêiner associativo que use uma pesquisa chave, isso seria mais eficiente: o (log n) Pesquisa e remoção de tempo constante.
Um mapa de hash pode ser ainda melhor, perto da constante pesquisa e remoção de tempo.
Para o que você está sugerindo, ou seja, apagando pelo ponteiro do objeto, você pode usar o std :: definido para o seu tipo T. Em seguida, use mySet.erase( pt );
onde PT é o seu ponteiro. Você precisa gerenciar a vida útil de seus ponteiros, é claro, mas o fato de saber qual deles apagar sua coleção sugere que você tem uma cópia em outro lugar.
Você pode usar std :: set, sharedptrless>
onde você define sharedptr sem a seguinte maneira:
template< typename T >
struct SharedPtrLess
{
bool operator()( boost::shared_ptr<T> left, boost::shared_ptr<T> right ) const
{
return std::less<T>()( left.get(), right.get());
}
};