容器的比较
vector:元素保存在连续空间中。可变大小数组,支持快速随机访问,在尾部之外的位置插入或删除可能很慢
list:双向列表,只支持顺序访问。在任何位置插入或删除都很快
forward_list:单项列表,只支持单向顺序访问。在链表任何位置插入或者删除都很快
deque:双端队列,支持快速随机访问,在头尾插入,删除很快
string :元素保存在连续空间中。和vector相似,但专门用于字符。随机访问快。在尾部插入或者删除快
array:固定数组,支持快速随机访问,不支持插入和删除。可以复制
常见操作:
push_back: array 和 forward_list 不支持,其他都支持
push_front:list , forward_list 和deque 支持, 其他不支持
insert: vector, deque, list, string 均支持insert. forward_list 的insert 版本较为特殊。
insert(iter, "Hello")会将hello 插入iter的前面
std::forward_list<int> fls = { 1,2,3 };
auto prev = fls.before_begin();
auto cur = fls.begin();
cur = fls.erase_after(prev); //删除prev指向位置之后的元素,返回一个指向被删除元素之后的迭代器,如不存在,则返回尾后元素
print(fls);//2 3
auto prev2 = fls.insert_after(fls.begin(),10);//在迭代器后的位置插入元素,返回一个指向最后一个插入元素的迭代器,如果函数第一个元素是尾后迭代器,则函数未定义
print(fls);//2 10 3 `
迭代器
STL按照算法要求的迭代器操作分类5个迭代器类别。
—-输入迭代器
只读不写,单遍扫描,只能递增
支持的操作:比较两个迭代器相等或者不等,推进迭代器前置或者后置递增运算,读取元素的解引用运算符(*),箭头运算符(->)。
递增输入迭代器可能导致其它指向流的迭代器失效,导致不能保证输入迭代器的状态可以保存下来并用来访问元素。因此只能用于单遍扫描算法
—-输出迭代器
只写不读,单遍扫描,只能递增
支持的操作:推进迭代器的前置或者后置递增运算。 解引用运算符(*)
—-前向迭代器
可读写,多遍扫描,只能递增
—-双向迭代器
可读写,多遍扫描,可递增递减
—-随机访问迭代器
可读写,多遍扫描,支持全部迭代器运算
适配器
适配器是一种机制,能使某种事物的行为看上去像另外一件事物一样。比如一个容器适配器接受一种已有的容器类型,使其行为看起来像一种不同的类型。stack 接受一个顺序容器(如vector, list 等),并使其操作起来像一个stack,而不再是原来的容器类型。
容器,迭代器,函数都有适配器。
容器适配器
主要有stack,queue,priority_queue等
迭代器适配器
插入迭代器
back_inserter, front_inserter, inserter
三个常见的迭代器适配器。back_inserter 和 front_inserter 接受一个容器作为参数,inserter 包含两个参数,第一个是容器,第二个是指向给定容器的迭代器。
std::list<int> ls1 = { 1,2,3 };
std::list<int> ls2 = { 4 };
std::list<int> ls3 = { 5 };
std::list<int> ls4 = { 6 };
copy(ls1.begin(), ls1.end(), std::back_inserter(ls2));
print(ls2); //4,1,2,3
copy(ls1.begin(), ls1.end(), std::front_inserter(ls3));
print(ls3); //3,2,1,5
copy(ls1.begin(), ls1.end(), std::inserter(ls4, ls4.begin()));
print(ls4);//1,2,3,6
iostream迭代器
标准库4个迭代器类型
ostream_iterator, istream_iterator, ostreambuf_iterator, istreambuf_iterator
//复杂式
std::istream_iterator<int> in_ite(std::cin);
std::istream_iterator<int> eof;
std::vector<int> test;
while (in_ite != eof)
{
test.push_back(*in_ite++);
}
print(test);
std::cin.clear();
std::cin.ignore();//清除输入缓冲区
//std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');//清除缓冲区的当前行
//简单式
std::istream_iterator<int> in_ite2(std::cin), eof2;
std::vector<int> test2(in_ite2, eof2);
print(test2);
//结合算法和输入流迭代器
std::istream_iterator<int> in_it(std::cin);
std::istream_iterator<int> eof;
std::cout << std::accumulate(in_it, eof, 0) << std::endl;
//输出流
//复杂式
for (auto e : test)
{
*out_it++ = e;
}
//简单式
std::ostream_iterator<int> out_it(std::cout, "=="); //每个元素之间被插入了"=="间隔,每次向out_it赋值, 写操作都会被提交
copy(test.begin(), test.end(), out_it);
反向迭代器
适配器reverse_interator
除了forward_list, 其他容器都支持反向迭代器
std::ostream_iterator<char> out_it2(std::cout, "!!");
std::string line = "FIRST,MIDDLE,LAST";
reverse_interatorfl = std::find(line.crbegin(), line.crend(), ',');
copy(fl.base(), line.cend(), out_it2); //L!!A!!S!!T
// 这里fl 指向LAST和MIDDLE 之间的逗号, 而fl.base()指向的是LAST 的第一个字符L,保证了[line.crbegin, fl) 和 [fl.base(), line.cend())指向的是line 中相同的范围。同样
crbegin()指向最后一个元素,而cend()指向最后一个元素的末尾(不存在的元素), 二者也相差一位, 同样的效果