C++ C++;列出擦除结束()-列表中的1个元素

C++ C++;列出擦除结束()-列表中的1个元素,c++,list,stl,listiterator,stdlist,C++,List,Stl,Listiterator,Stdlist,我有一个std::list events,我想删除该列表中除最后一个之外的所有元素。因此,我想做(如建议的那样): std::list::iterator it=events.begin();//列表顶部的Init迭代器 而(it!=*std::advance(events.end(),-1))events.erase(it++); 不幸的是,上述操作不起作用,因为它会产生错误: error: invalid initialization of non-const reference of t

我有一个
std::list events
,我想删除该列表中除最后一个之外的所有元素。因此,我想做(如建议的那样):

std::list::iterator it=events.begin();//列表顶部的Init迭代器
而(it!=*std::advance(events.end(),-1))events.erase(it++);
不幸的是,上述操作不起作用,因为它会产生错误:

error: invalid initialization of non-const reference of type ‘std::_List_iterator<node_info>&’ from an rvalue of type ‘std::__cxx11::list<node_info>::iterator {aka std::_List_iterator<node_info>}’
             while(it!=*std::advance(event_heap.end(),-1)){
错误:从类型为“std::”的右值初始化类型为“std:”的非常量引用无效。cx11:”列表::迭代器{aka std::”列表\迭代器}
while(it!=*std::advance(event_heap.end(),-1)){
但是,不应该返回迭代器吗?我做错了什么

但是,list::end不应该返回迭代器吗

是,但将非常量引用作为其第一个参数,而
事件\u heap.end()
是一个临时变量,不能绑定到非常量引用

std::advance
不返回任何内容(即
void
),因此您不能在其上使用
运算符*
,也不能将其与
运算符进行比较

直接固定方式如下所示:

std::list<some_object>::iterator it = events.begin();
auto one_before_end = events.end();
std::advance(one_before_end, -1); // or --one_before_end;
while (it != one_before_end) events.erase(it++);
这是一个典型的用法。 如果您想要删除除最后一个元素之外的所有元素,最惯用的方法是在您的终端迭代器上使用(基本上使用
std::advance

myList.erase(myList.begin(), std::prev(myList.end()));
例如:

#include <iostream>
#include <iterator>
#include <list>

int main(){
    std::list<int> ls = {3, 5, 9, 2};

    if(!ls.empty())
        ls.erase(ls.begin(), std::prev(ls.end()));

    for(auto x : ls)
        std::cout << x << std::endl;

    return 0;
}

正如Remy Lebeau在评论中指出的,对于非C++11编译器,您可以只使用
std::advance()
,如中所述,为什么不使用
std::list::erase
?events.erase(events.begin(),--(events.end());
?您应该使用
std::list::erase())
,但作为一种替代方法,您可能可以将
向后推()
项向后推()到一个临时
std::list
,然后将
std::swap()
项与主
std::list
,例如:
std::list temp;temp.向后推(events.back());std::swap(events,temp);
当临时文件超出范围时,它将释放所有未保存的项目。添加到Remy的注释中,您可以将对象移动到临时文件列表中,而不是复制请注意,
std::prev()
在C++11中是新的。对于早期版本,您必须继续使用
std::advance()
@RemyLebeau,谢谢,修复了。:-)通常,在执行
prev(ls.end())之前,您应该检查
!ls.empty()
或等效感谢@songyuanyao和所有您的启发性回复!@NathanOliver@Beta:我忘了在擦除之前,我需要对单个列表元素执行一些额外的操作。因此我需要逐个擦除列表元素。因此,
while
循环可能是最直接的方式或者,如果,我可以使用带有
std::list::remove\u的函子谓词。。。
myList.erase(myList.begin(), std::prev(myList.end()));
#include <iostream>
#include <iterator>
#include <list>

int main(){
    std::list<int> ls = {3, 5, 9, 2};

    if(!ls.empty())
        ls.erase(ls.begin(), std::prev(ls.end()));

    for(auto x : ls)
        std::cout << x << std::endl;

    return 0;
}
2