Контейнер forward_list представляет односвязный список, то есть такой список, где каждый элемент хранит указатель на следующий элемент. Для использования данного типа списка необходимо подключить заголовочный файл forward_list.
Создание односвязного списка:
std::forward_list<int> list1; // пустой список std::forward_list<int> list2(5); // list2 имеет 5 элементов, каждый из которых имеет значение по умолчанию std::forward_list<int> list3(5, 2); // list3 состоит из 5 чисел, каждое число равно 2 std::forward_list<int> list4{ 1, 2, 4, 5 }; // list4 состоит из чисел 1, 2, 4, 5 std::forward_list<int> list5 = { 1, 2, 3, 4, 5 }; // list5 состоит из чисел 1, 2, 3, 4, 5 std::forward_list<int> list6(list4); // list6 - копия списка list4 std::forward_list<int> list7 = list4; // list7 - копия списка list4 std::forward_list<int> list8({ 1, 2, 3, 4, 5, 6 }); // list8 состоит из чисел 1, 2, 3, 4, 5, 6
Напрямую в списке forward_list можно получить только первый элемент. Для этого применяется функция front(). Для перебора элементов также можно использовать цикл:
#include <iostream> #include <forward_list> int main() { std::forward_list<int> numbers { 1, 2, 3, 4, 5 }; int first {numbers.front()}; // 1 std::cout << "First: " << first << std::endl; for (int n : numbers) std::cout << n << "\t"; std::cout << std::endl; }
Также для перебора и получения элементов можно использовать итераторы
#include <iostream> #include <forward_list> int main() { std::forward_list<int> numbers{ 1, 2, 3, 4, 5 }; auto current = numbers.begin(); // итератор на начало списка auto end = numbers.end(); // указатель на конец списка while (current != end) { std::cout << *current << "\t"; current++; } std::cout << std::endl; }
Причем класс forward_list добавляет ряд дополнительных функций
для получения итераторов: before_begin() и cbefore_begin(). Обе функции возвращают итератор (вторая функция возвращает константный итератор const_iterator
) на
несуществующий элемент непосредственно перед началом списка. К значению по этому итератору обратиться нельзя.
#include <iostream> #include <forward_list> int main() { std::forward_list<int> numbers{ 1, 2, 3, 4, 5 }; auto prev = numbers.before_begin(); auto end = numbers.end(); while (++prev != end) { std::cout << *prev << "\t"; } std::cout << std::endl; }
По умолчанию класс forward_list не определяет никаких функций, которые позволяют получить размер контейнера. В этом классе только функция max_size(), которая позволяет получить масимальный размер контейнера.
Функция empty() позволяет узнать, пуст ли список. Если он пуст, то функция возвращает значение true, иначе возвращается значение false:
std::forward_list<int> numbers{ 1, 2, 3, 4, 5 }; if (numbers.empty()) std::cout << "The forward_list is empty" << std::endl; else std::cout << "The forward_list is not empty" << std::endl;
Для изменения размера контейнера можно использовать функцию resize(), которая имеет две формы:
resize(n): оставляет в списке n первых элементов. Если список содержит больше элементов, то он усекается до первых n элементов. Если размер списка меньше n, то добавляются недостающие элементы и инициализируются значением по умолчанию
resize(n, value): также оставляет в списке n первых элементов. Если размер списка меньше n, то добавляются недостающие элементы со значением value
Использование функции:
std::forward_list<int> numbers{ 1, 2, 3, 4, 5, 6 }; numbers.resize(4); // оставляем первые четыре элемента - numbers = {1, 2, 3, 4} numbers.resize(6, 8); // numbers = {1, 2, 3, 4, 8, 8}
Функция assign() позволяет заменить все элементы списка определенным набором. Она имеет следующие формы:
assign(il): заменяет содержимое контейнера элементами из списка инициализации il
assign(n, value): заменяет содержимое контейнера n элементами, которые имеют значение value
assign(begin, end): заменяет содержимое контейнера элементами из диапазона, на начало и конец которого указывают итераторы begin и end
Применение функции:
std::forward_list<int> numbers{ 1, 2, 3, 4, 5 }; numbers.assign({ 21, 22, 23, 24, 25 }); // numbers = { 21, 22, 23, 24, 25 } numbers.assign(4, 3); // numbers = {3, 3, 3, 3} std::list<int> values{ 6, 7, 8, 9, 10, 11 }; auto start = ++values.begin(); // итератор указывает на второй элемент из values auto end = values.end(); numbers.assign(start, end); // numbers = { 7, 8, 9, 10, 11 }
Функция swap() обменивает значениями два списка:
std::forward_list<int> list1{ 1, 2, 3, 4, 5 }; std::forward_list<int> list2{ 6, 7, 8, 9}; list1.swap(list2); // list1 = { 6, 7, 8, 9}; // list2 = { 1, 2, 3, 4, 5 };
Для добавления элементов в forward_list применяются следующие функции:
push_front(val): добавляет объект val в начало списка
emplace_front(val): добавляет объект val в начало списка
emplace_after(p, val): вставляет объект val после элемента, на который указывает итератор p. Возвращает итератор на вставленный элемент. Если p представляет итератор на позицию после конца списка, то результат неопределен.
insert_after(p, val): вставляет объект val после элемента, на который указывает итератор p. Возвращает итератор на вставленный элемент.
insert_after(p, n, val): вставляет n объектов val после элемента, на который указывает итератор p. Возвращает итератор на последний вставленный элемент.
insert_after(p, begin, end): вставляет после элемента, на который указывает итератор p, набор объектов из другого контейнера, начало и конец которого определяется итераторами begin и end. Возвращает итератор на последний вставленный элемент.
insert_after(p, il): вставляет после элемента, на который указывает итератор p, список инициализации il. Возвращает итератор на последний вставленный элемент.
Применение функций:
#include <iostream> #include <list> #include <forward_list> int main() { std::forward_list<int> numbers{ 7, 8 }; numbers.push_front(6); // добавляем в начало число 6 // numbers = { 6, 7, 8 } numbers.emplace_front(-3); // добавляем в начало число -3 // numbers = { -3, 6, 7, 8 } auto iter = numbers.begin(); iter = numbers.emplace_after(iter, -2); // добавляем после итератора число -2 // numbers = { -3, -2, 6, 7, 8 } iter = numbers.insert_after(iter, -1); // numbers = { -3, -2, -1, 6, 7, 8 } iter = numbers.insert_after(iter, 3, 0); // добавляем три нуля // numbers = { -3, -2, -1, 0, 0, 0, 6, 7, 8 } std::list<int> values{ 1, 2, 3 }; iter = numbers.insert_after(iter, values.begin(), values.end()); // добавляем все элементы из values // numbers = { -3, -2, -1, 0, 0, 0, 1, 2, 3, 6, 7, 8 } numbers.insert_after(iter, { 4, 5 }); // добавляем список { 4, 5 } // numbers = { -3, -2, -1, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8 } for(int n : numbers) std::cout << n << "\t"; std::cout << std::endl; }
Чтобы удалить элемент из контейнера forward_list, можно использовать следующие функции:
clear(): удаляет все элементы
pop_front(): удаляет первый элемент
erase_after(p): удаляет элемент после элемента, на который указывает итератор p. Возвращает итератор на элемент после удаленного
erase_after(begin, end): удаляет диапазон элементов, на начало и конец которого указывают соответственно итераторы begin и end. Возвращает итератор на элемент после последнего удаленного
Использование функций:
std::forward_list<int> numbers{ 1, 2, 3, 4, 5, 6, 7}; numbers.pop_front(); // numbers = { 2, 3, 4, 5, 6, 7}; auto iter = numbers.erase_after(numbers.begin()); // numbers = { 2, 4, 5, 6, 7 }; // iter указывает на элемент 4 numbers.erase_after(iter, numbers.end()); // numbers = { 2, 4 };