list本质是一个双向链表,其模板定义如下:
namespace std{
template<class T,
class Allocator = allocator<T> >
class list;
}
与vector一样,list也要求元素是可赋值、可拷贝的。
基本操作
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> c;
//增
c.insert(c.begin(),2);
c.push_back(2);
c.push_front();
c.pop_back();
c.pop_front();
//删
c.remove(2);
// c.remove_if(op);
// c.erase(pos); //返回下一元素位置
//改
*c.begin() = 10;
c.clear();
return 0;
}
以上即list最基本的一些操作,如果要详细了解,可访问:链接。
erase函数
erase函数可以用于删除迭代器所指向的元素,通常我们会在遍历过程中进行这种操作,我们需要注意的是,如果该迭代器所指向的元素被删除了,该迭代器也失效了,但是,erase返回下一元素的位置,解决了这个问题,我们可以像下面这样使用:
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> c;
for(int i = 0 ; i < 10 ; ++i)
c.push_back(i);
iter = c.begin();
for( ; iter != c.end() ; )
{
if(*iter == 5)
{
iter = c.erase(iter);
}
else
{
++iter;
}
}
return 0;
}
值得一提的是,这种方式同样适用于vector的erase函数,但是却不适用于map的erase函数。
remove函数
虽然STL为容器提供了remove()函数,但是在面对list时,我们应当调用其成员函数remove(),而不是像vector和deques那样调用STL算法。
如果要移除所有“与某值相等”的元素,那么可以使用:
std::list<Elem> coll;
coll.remove(val);
如果你想删除满足某个条件的元素,那么可以使用remove_if();
特殊变动性操作
由于list是基于链表实现的,所以在改变次序方面具有优势,因此list也提供了很多函数用于这些操作。如下:
但需要注意的是:进行两个list的操作时,必须确保他们的元素类型是一致的。
List迭代器
由于List不能随机存取,迭代器是双向而非随机迭代器,所以凡是用到随机存取迭代器的算法(涉及到操作元素顺序的算法,例如排序算法),都不能调用,但是List提供了sort() 函数;
list与vector
list与vector存在以下区别:
- list不支持随机存取,如果要访问某个元素,那么你必须遍历到该元素,然后通过迭代器操作。
- 任何位置上安插、删除都很快,始终都是常数时间。
- 插入、删除并不会导致指向元素的指针、引用及迭代器失效,因为它不需要移动元素,也不会重新分配内存。
异常处理
list对于异常安全性提供了最佳支持,几乎所有操作都是要么成功,要么无效。除了仅有的几个操作没有如此保证,包括赋值运算、sort,但是它们也有基本保证:异常发生时不会泄露资源。