STL: práticas recomendadas para remover elementos de contêineres

Fale primeiro

Talvez os designers da STL acreditem que a consistência da API é muito importante, o nome curto e bonito da função seja muito importante e a capacidade do cérebro humano não seja importante ...

Classificação de contêiner

  • Recipientes de memória contínua (vecotr, deque, fila, string)
  • lista (sim, você é o mesmo fogo de artifício)
  • Contêineres associativos padrão (conjunto, multiset, mapa, multimap)

Contêiner de memória contínua

Primeiro, deixe dois pontos claros:

  1. Remover aqui significa A função std :: remove é semelhante a remove_if. Em vez de std :: list :: remove, o último será mencionado mais tarde.
  2. Além disso, a versão de elemento único de exclusão e a versão do intervalo de exclusão de exclusão retornarão o iterador do próximo elemento do elemento / intervalo excluído, porque a exclusão invalidará o iterador de todos os elementos na posição subseqüente.

Nenhuma exclusão de iteração: remove / remove_if coopera com a exclusão

Como o design do módulo do algoritmo STL é dissociado do tipo de contêiner específico, ou seja, ele recebe e opera apenas os iteradores de vários tipos de contêineres, e o iterador oculta os detalhes específicos da iteração do elemento no contêiner, portanto, std: : remove realmente não pode excluir o elemento , porque ele conhece apenas o iterador do contêiner e não conhece o método de exclusão do contêiner.
Para contêineres de memória contínua, o comportamento de std :: remove e std :: remove_if é mover todos os elementos elegíveis para o final do contêiner e retornar o iterador do primeiro elemento a ser excluído. No momento, esses elementos podem ser realmente excluídos pelo método apagar . O código de exemplo é o seguinte:

vector<int> vi{1,2,2,3,4,5,6,6};
vi.erase(remove(vi.begin(), vi.end(), 2), vi.end()); // 不使用erase的返回值
vi.erase(remove_if(vi.begin(), vi.end(), [](int i){  // 不使用erase的返回值
    return i > 4;            
}), vi.end());

Exclusão iterativa: e se você quiser excluir um elemento e fazer outra coisa?

Naturalmente, é fácil pensar em excluir com apagar. Mas, para contêineres de memória contínua, após chamar apagar para excluir um único elemento para invalidar o iterador dos seguintes elementos (é claro, o excluído também falha), o loop ainda está em execução e o iterador invalidado excluído é adicionado novamente e o comportamento é indefinido. Portanto, use o valor de retorno de apagar:

vector<int> vi{1,2,2,3,4,5,6,6};
for(auto iter = vi.begin(); iter != vi.end(); /*这里啥也不干*/)
{
    if(*iter == 2)
    {
        iter = vi.erase(iter); //这里隐含了一次++
    }
    else
    {
        ++iter;
    }
}

Lista

List usa contêiner de memória contínua para exclusão de intervalo e exclusão iterativa, mas é mais eficiente chamar a função list :: remove () diretamente , porque para a lista vinculada, é um desperdício demais jogar todos os valores a serem excluídos e excluí-los uniformemente. , A exclusão de um único elemento na lista vinculada é O (1).

Eu sempre sinto que o STL é um pouco superprojetado aqui ...

Acho que você gosta

Origin www.cnblogs.com/jo3yzhu/p/12705988.html
Recomendado
Clasificación