一、vector用于实现数组的功能,相当于在数组的基础上封装了一些常用的功能。
函数名称 | 功能 |
push_back | 在尾部添加一个元素 |
pop_back | 在尾部删除一个元素 |
clear | 清空所有元素 |
at | 按索引访问某个位置的元素 |
front | 返回头元素 |
back | 返回尾元素 |
size | 返回元素的个数 |
capacity | 返回房前容量 |
risize | 改变容量的大小 |
insert | 在中间插入元素 |
erase | 删除中间元素 |
vector和普通的数组一样。具有容量的概念,可以推断,vector内部是有一个缓冲区来存储元素的,类似于下面的代码
template<typename T>
class vector
{
private:
T* m_buffer; //缓冲区
int m_capacity; //缓冲区的大小
};
可见,vector内容上还是数组,只是外在形式上比较单纯的数组更易于使用了,它对外封装了前面所列的接口函数,使读者非常方便的操纵数组
在创建vector对象时,可以显示的指定其初始大小,例如,以下的代码将初始容量设置位128,这意味着其内部创建了一个可以容纳128个元素的缓冲区
vector<int> arr(128);
int capacity = arr.capacity(); //容量:128
int size = arr.size(); // 大小:128,已经包含了128个元素,并且此时的128个元素都为0
//在这种情况下,size和capacity相等
二、用at函数访问数组中的元素
vector<int> arr(128);
for(int i=0; i<arr.capacity(); i++)
{
int& p = arr.at(i);
p = 0; //全部初始化为0
}
看起来很简单,直接用at函数可以得到元素的引用(左值),然后直接操作这个引用即可。实际上vector还重载了操作符[ ],因此以下的代码是等价的
int &p = arr.at(0);
int &p = arr[0];
使用操作符 [ ],会显得更简洁一些,但是值得强调的是,如同数组一样,要注意越界问题,无论是at还是[ ] ,传入的索引值都要在正确的范围之内(0 <= index <= capacity - 1)。
注意上述的arr不是数组,而是类
三、vector的一个显著的特点是,其容量可以动态调整的,使用push_back可以在尾部追加一个元素,使用pop_back删除 尾部元素
例如:
vector<int> arr; //capacity:0, size:0
arr.push_back(1); //capacity:4,size:1
当创建对象时如果没有指定capacity,则默认为0,此时capacity和size都是0(此时的缓冲区也是没有创建的),当使用push_back在末尾添加一个元素时:
(1)如果还有空间可用(size < capacity),则size加1,capacity不变
(2)如果空间已满(size = capacity),则重新申请一个较大的缓冲区,再把原有的拷贝到新缓冲区,再把新元素追加在后面。此时size加1,capacity为新的缓冲区的容量(一般新容量是原有的capacity+4,也有可能是每增加一个元素,capacity也增加1,具体取决于STL的库实现)。
由此可见,push_back并不是节省cpu的操作,它是反复地申请新缓冲区和拷贝大段数据,所以,在使用vector时候,应该预先估计一下,程序运行时可能需要的最大容量,并在初始化的时候指定其capacity参数,如果在迫不得已的情况下一定要调整容量的话,可以使用resize函数,尽量一步调整到位,不要多次反复的使用resize
四、clear函数用于清空元素,size归0,而capacity不变,内部缓冲区不重新申请