Класс forward_list: вставка элементов

Вставить элементы позволяют следующие методы:

  • push_front() — добавляет элемент в начало списка (доступно копирование и перемещение значения):
std::forward_list<int> arr = {2, 3};
arr.push_front(1);
for (int &el : arr) std::cout << el << ' ';
std::cout << std::endl; // 1 2 3
  • emplace_front() — создает объект, передавая конструктору указанные через запятую значения, а затем добавляет объект в начало списка. Начиная со стандарта C++17, метод возвращает ссылку на созданный объект:
class C {
public:
   int x, y;
   C(int a, int b) : x(a), y(b) { }
};
// ... Фрагмент опущен ...
std::forward_list<C> arr;
arr.push_front(C(20, 20));
arr.emplace_front(10, 40);
for (C &el : arr) std::cout << el.x << ' ';
std::cout << std::endl;     // 10 20
  • insert_after() — вставляет один или несколько элементов после позиции pos, заданной с помощью итератора. Прототипы метода:
iterator insert_after(const_iterator pos, const value_type &val);
iterator insert_after(const_iterator pos, value_type &&val);
iterator insert_after(const_iterator pos, size_type count,
                      const value_type &val);
template<typename InputIterator>
   iterator insert_after(const_iterator pos, InputIterator first,
                         InputIterator last);
iterator insert_after(const_iterator pos,
                      initializer_list<value_type> list);

Первые два прототипа вставляют элемент после позиции pos, на которую указывает итератор и возвращают итератор, ссылающийся на вставленный элемент. Обратите внимание: итераторы односвязных списков не поддерживают операторы +, - и --, для перемещения итератора нужно использовать оператор ++ или функцию advance():

std::forward_list<int> arr = {10};
arr.insert_after(arr.before_begin(), 0); // В начало
std::forward_list<int>::iterator it = arr.begin();
std::advance(it, 1);                     // Перемещаем итератор
arr.insert_after(it, 55);                // В позицию 2
for (int &el : arr) std::cout << el << ' ';
std::cout << std::endl;                  // 0 10 55

Обратите внимание: в этом примере вместо метода begin(), мы воспользовались методом before_begin(), который возвращает итератор, ссылающийся на позицию перед первым элементом списка.

Простого способа добавить элемент в конец односвязного списка нет. Метод end() вернет итератор, ссылающийся на позицию после последнего элемента, а вернуться назад нельзя, т. к. итератор односвязного списка не поддерживает операторы - и --. Сначала придется вычислить позицию последнего элемента:

std::forward_list<int> arr = {1, 2, 3};
auto it1 = arr.begin(), it2 = arr.end();
while (std::next(it1) != it2) ++it1;
std::cout << *it1 << std::endl;          // 3
arr.insert_after(it1, 4);                // В конец списка
for (int &el : arr) std::cout << el << ' ';
std::cout << std::endl;                  // 1 2 3 4

Если нужно добавить несколько элементов в конец списка, то можно сохранить итератор, возвращаемый методом insert_after() после вставки, и использовать его для следующей операции:

std::forward_list<int> arr;
auto it = arr.before_begin();
it = arr.insert_after(it, 1);            // В начало списка
it = arr.insert_after(it, 2);            // В конец списка
arr.insert_after(it, 3);                 // В конец списка
for (int &el : arr) std::cout << el << ' ';
std::cout << std::endl;                  // 1 2 3

Третий прототип вставляет count копий элемента val после позиции pos, на которую указывает итератор:

std::forward_list<int> arr = {1, 2, 3};
arr.insert_after(arr.before_begin(), 3, 0);
for (int &el : arr) std::cout << el << ' ';
std::cout << std::endl; // 0 0 0 1 2 3

Четвертый прототип вставляет элементы из диапазона, ограниченного итераторами first и last, после позиции pos, на которую указывает итератор:

std::forward_list<int> arr1 = {1, 2, 3}, arr2 = {4, 5, 6};
arr2.insert_after(arr2.before_begin(), arr1.begin(), arr1.end());
for (int &el : arr2) std::cout << el << ' ';
std::cout << std::endl; // 1 2 3 4 5 6

Пример вставки элементов из обычного массива:

int arr1[] = {1, 2, 3};
std::forward_list<int> arr2 = {4, 5, 6};
arr2.insert_after(arr2.before_begin(), arr1, arr1 + 3);
for (int &el : arr2) std::cout << el << ' ';
std::cout << std::endl; // 1 2 3 4 5 6

Пятый прототип вставляет элементы из списка инициализации после позиции pos, на которую указывает итератор:

std::forward_list<int> arr = {4, 5, 6};
arr.insert_after(arr.before_begin(), {1, 2, 3});
for (int &el : arr) std::cout << el << ' ';
std::cout << std::endl; // 1 2 3 4 5 6
  • emplace() — создает объект, передавая конструктору указанные через запятую значения во втором и последующих параметрах, а затем добавляет объект после позиции, заданной в первом параметре. Метод возвращает итератор, ссылающийся на вставленный элемент. Добавим один объект в начало списка и два объекта в конец списка:
std::forward_list<C> arr;
auto it = arr.before_begin();
it = arr.emplace_after(it, 10, 20);
it = arr.emplace_after(it, 30, 40);
arr.emplace_after(it, 50, 60);
for (C &el : arr) std::cout << el.x << ' ';
std::cout << std::endl; // 10 30 50
  • swap() — меняет элементы двух списков местами:
std::forward_list<int> arr1 = {1, 2, 3}, arr2 = {4, 5, 6};
arr1.swap(arr2);
for (int &el : arr1) std::cout << el << ' ';
std::cout << std::endl; // 4 5 6
for (int &el : arr2) std::cout << el << ' ';
std::cout << std::endl; // 1 2 3

Вместо метода swap() можно воспользоваться одноименной функцией:

std::forward_list<int> arr1 = {1, 2, 3}, arr2 = {4, 5, 6};
std::swap(arr1, arr2);
for (int &el : arr1) std::cout << el << ' ';
std::cout << std::endl; // 4 5 6
for (int &el : arr2) std::cout << el << ' ';
std::cout << std::endl; // 1 2 3

Учебник C++ (MinGW-W64)
Учебник C++ (MinGW-W64) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов