#include "utils.h" // Для printContainer(): см. 7.10
using namespace std;
int main() {
list
lstStr.push_back("On");
lstStr.push_back("a");
lstStr.push_back("cloudy");
lstStr.push_back("cloudy");
lstStr.push_back("day");
list
// Найти то что требуется, с помощью find
p = find(lstStr.begin(), lstStr.end(), "day");
p = lstStr.erase(p); // Теперь p указывает на последний элемент
// Или для удаления всех вхождений чего-либо используйте remove
lstStr.erase(remove(lstStr.begin(), lstStr.end(), "cloudy"),
listStr.end());
printContainer(lstStr); // См. 7.10
}
Для удаления одного или нескольких элементов из контейнера используйте метод erase
erase
: один принимает единственный аргумент iterator
, который указывает на элемент, который требуется удалить, а другой принимает два аргумента, которые представляют диапазон удаляемых элементов. Чтобы удалить один элемент, получите iterator
, указывающий на этот элемент, и передайте этот iterator
в erase
, как в примере 7.2.p = find(lstStr.begin(), lstStr.end(), "day");
p = lstStr.erase(p);
В результате объект, на который указывает p
В последовательностях erase
iterator
, который ссылается на первый элемент, следующий непосредственно за последним удаленным элементом, что может оказаться end
, если был удален последний элемент последовательности. Сложность этой операции для каждого контейнера различна, так как последовательности реализованы по- разному. Например, из-за того, что все элементы vector
хранятся в непрерывном фрагменте памяти, удаление из него элемента, кроме первого и последнего, с целью заполнения образовавшегося промежутка требует сдвига всех последующих элементов в сторону начала. Это приводит к значительному снижению производительности (в линейном отношении), и именно по этой причине не следует использовать vector
, если требуется удалять (или вставлять, что в данном случае приводит к таким же последствиям) элементы где-либо, кроме концов. Более подробно этот вопрос обсуждается в рецепте 6.2.В ассоциативных контейнерах erase
void
. При удалении одного элемента сложность имеет вид амортизированной константы, а при удалении диапазона — логарифмической зависимости плюс количество удаляемых элементов. Причина этого заключается в том, что ассоциативные контейнеры часто реализуются как сбалансированные деревья (например, красно-черное дерево).erase
). Рассмотрим такую строку из примера 7.2.lstStr.erase(std::remove(lstStr.begin(), lstStr.end(), "cloudy"),
lstStr.end());
Обратите внимание, что я использую erase
list
все вхождения слова «cloudy», remove
возвращает iterator
, который передается в erase
как начало удаляемого диапазона, a end
передается в erase
как конечная точка диапазона. В результате удаляются все объекты obj
(вызывая их метод delete
) из диапазона, для которого obj == "cloudy"
равно истине. Но поведение этой строки может оказаться не совсем таким, как ожидается. Здесь мне требуется пояснить некоторую терминологию.remove
iterator
, который ссылается на первый элемент, следующий за этими перемещенными элементами. Затем вы должны вызвать erase
для контейнера, чтобы удалить объекты между [p, end)
, где p
— это iterator
, возвращенный remove
.