使用std::copy复制std::list,然后使用std::list::erase删除内容

4

在下面的示例代码中,我将示例列表赋值为数字,然后尝试使用std::copy复制容器,但问题是在运行时它会显示"cannot dereference end list iterator"

我的问题是如何复制该列表,以便将复制的范围插入到列表的末尾?

至末尾,因为我之后需要能够删除重复的范围,这就是为什么我将新范围的开头保存到迭代器中的原因。

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

void print(std::list<int>& ref)
{
    for (auto& 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;
}
2个回答

2
你可以使用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());

可以,你知道是否可以使用std :: copy来完成这个操作吗? - user11157650
std::copy_n,std::next()和size()绝对是解决这个问题的关键! - user11157650

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

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

不幸的是,我们无法在copy()中使用终止迭代器,因为这可能会导致无限循环,因为新元素一直添加在结束迭代器和当前迭代器之间。


尽管您的解决方案与lubgr的解决方案等效,但由于std::next()更易读,我标记了他的答案。谢谢您的理解。 - user11157650
@zebanovich 注意,next(begin, n)的时间复杂度为O(n)。那个解决方案看起来更好,但可能会慢30%(计算节点触摸次数)。 - Michael Veksler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接