顺序容器简介
顺序容器,就是提供了快速顺序访问功能的容器。C++标准库中提供了以下顺序容器:
array 容量不可变的数组,不能插入和删除,支持随机访问
vector 容量可变的数组,插入和删除操作的性能不好,支持随机访问
list 双向链表,插入和删除的性能很好,但是不支持随机访问
forward_list 单向链表,不能逆序访问,不支持随机访问
deque 双端队列,支持随机访问
string 字符串类,专门用来保存和处理字符串
一般定义顺序容器的头文件和顺序容器的名字相同,如:
#include<vector> //定义vector的头文件
#include<list> //定义list的头文件
#include<string> //定义string的头文件
除string外,使用顺序容器需要声明类型,如储存int类型的容器为:
vector<int> intVector;
list<int> intList;
容器操作
1.迭代器
变量可以分为普通变量和常变量,迭代器也一样,可以分为普通迭代器和常迭代器。
普通迭代器可以对指向的元素进行读写,而常迭代器只能读不能写。可以通过顺序容器命名空间的iterator和const_iterator类型别名分别定义普通迭代器和常迭代器,也可以通过auto类型说明符自动获取迭代器的类型。
vector<int>::iterator it;//获取vector<int>容器的迭代器it
一些获取迭代器的成员函数:
begin() 获取指向容器首元素的迭代器
end() 获取指向容器尾元素后一个位置的迭代器
cbegin() 获取指向容器首元素的常迭代器
cend() 获取指向容器尾元素后一个位置的常迭代器
rbegin() 获取指向反向容器容器首元素的迭代器
rend() 获取指向容器尾元素后一个位置的常迭代器
crbegin() 获取指向反向容器容器首元素的常迭代器
crend() 获取指向容器尾元素后一个位置的常迭代器
下面是一些使用迭代器和获取迭代器函数的例子:
可以使用迭代器遍历顺序容器:
//vector<int>test;
for(auto it=test.begin();it!=test.end();it++)
cout<<*it;
当不需要对容器进行写访问时,通常使用常迭代器,上面的代码可以优化为:
//vector<int>test;
for(auto it=test.cbegin();it!=test.cend();it++)
cout<<*it;
当需要逆序访问容器时,使用反向迭代器:
//vector<int>test;
for(auto it=test.rbegin();it!=test.rend();it++)
cout<<*it;
C++顺序容器定义了自增,自减和解引用的运算符,使用起来很方便,但是需要注意的是,单向链表forward_list不支持逆序访问,也就没有自减运算符。
2.添加和删除元素
一些用于添加和删除操作的成员函数:
insert() 在指定位置插入一个元素
emplace() 在指定位置构造一个元素
erase() 删除指定位置的元素
clear() 删除所有元素
insert()和emplace()貌似差不多,都是在指定位置插入一个元素,但是有本质的不同:
insert()函数是插入一个已有的元素,不能直接直接调用对象的构造函数
emplace()函数是插入一个重新构造的元素,所以emplace()函数会根据参数调用对象的构造函数
在没有默认构造函数的类型中,我们会更直观的看出它们的不同:
//complex类没有默认构造函数
class complex{
public:
int a;
int b;
compex(int x,int y):a(x),b(y){}
}
vector<complex>test;//定义vector<complex>类型的容器
complex a(1,-1);
test.insert(test.begin(),a);//在test的首元素位置插入a
test.insert(test.begin(),complex(1,-1));//在test的首元素位置插入compelx(1,-1)
test.insert(test.begin(),1,-1);//错误,企图通过insert()调用complex的构造函数
test.emplace(test.begin(),1,-1);//正确,通过emplace()调用complex的构造函数
最后通过几个函数练习今天学习的内容:
//顺序访问vector容器
template<typename T>
void print(vector<T>test){
for(auto it=test.cbegin();it!=test.cend();it++)
cout<<*it<<' ';
cout.put(10);
}
//逆序访问vector容器
template<typename T>
void print(vector<T>test){
for(auto it=test.crbegin();it!=test.crend();it++)
cout<<*it<<' ';
cout.put(10);
}
//在迭代器范围内查找元素
template<typename T>
bool search(vector<T>::const_iterator begin,vector<T>::const_iterator end,vector<T>::value_type x){
for(auto it=begin;it!=end;it++)
if(*it==x)return true;
return false;
}