Дублирование std::list с помощью std::copy и удаление с помощью std::list ::erase

#c #list #copy

#c #Список #Копировать

Вопрос:

В приведенном ниже примере кода после присвоения примера списка с номерами я пытаюсь дублировать контейнер с помощью std::copy но проблема в том, что во время выполнения он говорит «не удается разыменовать итератор конечного списка».

мой вопрос в том, как мне дублировать список, чтобы дублированный диапазон был вставлен в конец списка?

до конца, потому что позже мне понадобится возможность удалять дублированный диапазон, поэтому я сохраняю начало нового диапазона в iterator.

 #include <iostream>
#include <list>
#include <algorithm>

void print(std::list<int>amp; ref)
{
    for (autoamp; num : ref)
    {
        std::cout << num << std::endl;
    }
}

int main()
{
    std::list<int> mylist{ 1, 2, 3, 4 };
    std::list<int>::iterator iter = mylist.end();

    std::cout << "INITIAL LIST NUMBERS" << std::endl;
    print(mylist);

    // duplicate list, will cause runtime error
    iter = std::copy(mylist.begin(), mylist.end(), --mylist.end());

    std::cout << "COPIED LIST IS NOW CONTAINS DUPLICATE NUMBERS" << std::endl;
    print(mylist);

    // remove previsous duplication
    mylist.erase(iter, mylist.end());

    std::cout << "AFTER REMOVAL OF COPIED LIST SHOULD BE SAME AS INITIAL LIST" << std::endl;
    print(mylist);

    std::cin.get();
    return 0;
}
  

Ответ №1:

Вы можете использовать std::copy_n . Это позволяет обойти проблему с std::copy , которая выполняла бы бесконечный цикл вставок при подаче с std::back_inserter(mylist) и всегда действительным mylist.end() итератором.

 const std::size_t n = mylist.size();
std::copy_n(mylist.cbegin(), n, std::back_inserter(mylist));
  

Удаление дублирования затем работает с

 mylist.erase(std::next(mylist.begin(), n), mylist.end());
  

Комментарии:

1. Это сработало, вы не знаете, возможно ли это сделать с помощью std:: copy?

2. std::copy_n, std::next() и size() определенно являются ключом к решению этой проблемы!

Ответ №2:

  if (!mylist.empty()) --iter;

 std::copy_n(mylist.begin(), mylist.size(), std::back_inserter(mylist));
 if (!mylist.empty())   iter;
  

К сожалению, мы не можем использовать конечный итератор в copy(), поскольку это может привести к бесконечному циклу, поскольку между конечным и текущим итераторами постоянно добавляются новые элементы.

Комментарии:

1. несмотря на то, что ваше решение эквивалентно решению lubgr, я пометил его ответ, потому что std:: next() выглядит более удобным для чтения, спасибо за понимание

2. @zebanovich обратите внимание, что next (begin, n) — это O (n). Это решение выглядит лучше, но может быть на 30% медленнее (с учетом затронутых узлов)