Radera – ta bort idiom

Radera -ta bort idiom är en vanlig C++ -teknik för att eliminera element som uppfyller ett visst kriterium från en C++ Standard Library- behållare.

Motivering

En vanlig programmeringsuppgift är att ta bort alla element som har ett visst värde eller uppfyller ett visst kriterium från en samling . I C++ kan detta uppnås med hjälp av en handskriven loop. Det är dock att föredra att använda en algoritm från C++ Standard Library för sådana uppgifter.

Member-funktionen radera kan användas för att ta bort ett element från en samling, men för behållare som är baserade på en array, såsom vektor , måste alla element efter det borttagna elementet flyttas framåt för att undvika "luckor" i samlingen. Att anropa radera flera gånger på samma behållare genererar mycket omkostnader från att flytta elementen.

Algoritmbiblioteket tillhandahåller remove- och remove_if - algoritmerna för detta. Eftersom dessa algoritmer fungerar på en rad element som betecknas av två framåt iteratorer, har de ingen kunskap om den underliggande behållaren eller samlingen.

Dessa algoritmer tar inte bort element från behållaren, utan flyttar alla element som inte passar borttagningskriterierna till framsidan av intervallet, och behåller den relativa ordningen för elementen. Detta görs i en enda passage genom dataområdet.

Eftersom inga element faktiskt tas bort och behållaren behåller samma storlek, har arrayens svans en längd som är lika med antalet "borttagna" föremål; dessa objekt finns kvar i minnet men i ett ospecificerat tillstånd. remove returnerar en iterator som pekar på det första av dessa svanselement så att de kan raderas med ett enda anrop för att radera .

Om du gör samma sak med endast radering resulterar det i lika många pass som det finns element att ta bort. För var och en av dessa omgångar måste alla element efter det raderade elementet flyttas, vilket är mer tidskrävande än att flytta element i en enda passage.

C++20

tillhandahålls de fria funktionerna std::erase och std::erase_if för STL-behållare. Dessa bekvämlighetsfunktioner kan användas för att utföra korrekt radering av element utan att programmeraren behöver uttryckligen använda idiomet radera-ta bort.

Begränsning

Idiomet radera–ta bort kan inte användas för behållare som returnerar const_iterator (t.ex.: set )

std::remove och/eller std::remove_if underhåller inte element som tas bort (till skillnad från std::partition , std::stable_partition ) . Således kan radera–ta bort endast användas med behållare som innehåller element med fullvärdessemantik utan att det uppstår resursläckor.

Exempel

Kompilatorutforskaren



 
 
 

        

    
        
        
  
    


  
  
     0         
  

  
     
  

  
     
  







 // Använd g++ -std=c++11 eller clang++ -std=c++11 för att kompilera.  #inkludera  <algoritm>  // remove and remove_if  #include  <iostream>  #include  <vector>  // den allmänna vektorbehållaren  bool  IsOdd  (  int  i  )  {  return  i  &  1  ;  }  void  Skriv ut  (  const  std  ::  vektor  <  int  >&  vec  )  {  for  (  const  auto  &  i  :  vec  )  {  std  ::  cout  <<  i  <<  ' '  ;  }  std  ::  cout  <<  '\n'  ;  }  int  main  ()  {  // Initialiserar en vektor som innehåller tal från 0-9.  std  ::  vektor  <  int  >  v  =  {  ,  1  ,  2  ,  3  ,  4  ,  5  ,  6  ,  7  ,  8  ,  9  };  Skriv ut  (  v  );  // Tar bort alla element med värdet 5.  v  .  erase  (  std  ::  remove  (  v  .  börja  (),  v  .  slut  (),  5  ),  v  .  slut  ());  Skriv ut  (  v  );  // Tar bort alla udda tal.  v  .  erase  (  std  ::  remove_if  (  v  .  start  (),  v  .  end  (),  IsOdd  ),  v  .  end  ());  Skriv ut  (  v  );  }  /*  Utdata:  0 1 2 3 4 5 6 7 8 9  0 1 2 3 4 6 7 8 9  0 2 4 6 8  */