文章目录
1.顺序容器的类型
顺序容器是C++语言STL中的重点,顺序容器提供了一种处理多个对象的快捷方法。
顺序容器的类型如下:
除了list和forward_list其他的元素都存放在连续的内存空间中。具体改使用哪种容器应该根据使用的方式来判断,如果需要随机访问则使用vector或者deque,如果使用频繁的插入元素则应该使用list,主要根据操作的类型选择容器。一般情况下使用vector,除非有更好的理由选择其他的容器。
每个容器都定义在一个头文件中,一般该头文件的名字就是该容器的名字。
2.迭代器以及容器的共有操作
迭代器就是用于访问容器的元素的工具,其行为类似于指针操作。迭代支持常见的运算操作(++、–、=、+、-、*等)。
迭代器范围
迭代器范围就是指两个迭代器的跨度,一般来说是begin()到end()的元素(一般不包括end,end指向最后一个元素的下一个位置)。
vector<int>::iterator it;//声明一个指向vector<int>中的元素的迭代器。
vector<int> vec;
auto it=bec.begin();//指向第一个元素
it++;//指向第二个元素;
常用还有反向迭代器、常量迭代器等。
容器常见操作:
3.容器的初始化
容器一般采用构造函数进行初始化,具体的初始化方式见下表:
标准库array
array和其他的容器有所不同,array具有固定大小,当我们初始化array时需要同时指出类型和大小。
array<int,42> arr;//保存42个int的数组
array<string,10> str;//保存十个string的数组
array<int,10>={10,12,11,15,14,35,45,48,56,12};//列表初始化
array<int,10>={10};//一个10和9个0,没有指出的默认为0;
array可以赋值,但是内置数组是不能直接赋值的
int digs[10]={0,1,2,3,4,5,6,7,8,9};
int a=digs;//错误,不能直接对数组赋值
array<int,10> nums={0};
array<int,10>nums_b=nums;//正确,array可以赋值。
4.赋值和swap
除array外,swap不对任何元素进行拷贝、删除、或插入操作,因此可以保证常数时间内完成。
5.向容器中添加元素
向容器中添加元素的方法有很多,不同的方法向容器中添加元素的方法有所差异,见下表:
当我们向一个容器中放入的是对象时,我们放入的是这个对象的拷贝,当我用容器操作对象时,源对象不会改变,如果我们想要改变源对象,则我们应该放入对象的指针或者引用。
empalace操作和一般操作有所不同,当我们调用一个emplace操作时,我们实际上是在调用构造函数向容器中初始化一个对象,我们传入emplace的参数必须和容器中存放的类型的构造函数相匹配。
c.empalce_back("zhangsan",15,"男");
这里要求c中存放的类型必须具备接收(string,int,string)这样的参数列表的构造函数,以上语句等价于
c.push_back(Person("zhangsan",15,"男"));
传入emplace的参数必须和相应类型的构造函数参数相匹配。
c.emplace();//调用默认构造函数
6.元素访问
对容器中的元素访问可以通过下标运算符以及一些函数,对容器的访问的方法具体如下表:
成员访问函数,返回的都是引用,如果一个容器是const对象,则返回const引用,否则返回普通引用。
if(!c.empty())
{
c.front()=42;//将42赋予c中的第一个元素
auto &v=c.back();//获得指向最后一个元素的引用
v=1024;//改变c中的元素
auto v2=c.back();//v2不是一个引用,它是c.back()的一个拷贝
v2=0;//为改变c中的元素
}
想要改变容器中的元素,必须将变量定义为引用类型。
7.删除元素
和添加元素类似,不同容器删除元素略微有些不同,如下表:
删除元素时必须保证元素是存在的,否则的会发生未定义错误,保证元素是存在的是程序员的任务。
forward_list的操作
单向列表的操作和其他的操作有所不同,因为forward_list的数据结构的特殊性,它不能执行指针的减操作,因而它的很多的操作比较特殊,具体如下表:
8.容器操作使得迭代器失效
当我们对容器进行操作时,有时会导致迭代器失效,具体什么情况下会导致迭代器失效要看我们操作时是否移动了迭代器所指向的元素 ,如果我们移动了一个迭代器指向的元素,那么这个迭代器指向的内存可能已经被回收了,此时使用迭代器将会产生未定义行为。
- 操作链表(list、forward_list)一般不会导致迭代器失效(不是删除迭代器指向的元素),因为链表的添加或者删除都不会导致元素的移动。
- vector和string当我们添加元素时,会导致容器空间的重新分配,此时指向的所有迭代器和引用会失效,当我们删除元素时,迭代器或者引用之前的元素仍然有效,迭代器或者引用之后的元素将会失效(删除元素时迭代器之后的元素将会被向前移动)
- deque容器在首尾以外的任何地方添加或删除元素将会导致迭代器失效,在首尾操作时其他迭代器仍然有效。
- 除链表外的任何容器的操作将会导致尾后迭代器(end()返回的迭代器)失效。
每次对容器操作后建议重新定位迭代器
9.capacity和size
容器的size是指目前容器中存放的元素的数目,而capacity是指容器在不重新分配空间的情况下能容纳的元素的最多数目。可用a.szie()
和a.capacity()
分别获取容器的大小和容量,而使用a.shrink_to_fit()
可以请求将多余的容器的内存归还给系统。即将capacity-size的多余内存归还,但仅是请求而已,具体是否真的执行有系统决定。