vector接口介绍&迭代器失效
注:主要介绍部分常用及重点接口
一、构造方法
构造函数
无参构造
一般使用这种空的vector对象要进行push_back或者调用resize进行扩容
vector<int> v1;//构造一个空对象
无参构造的对象,size和capacity都为0:
n个T类型构造
vector<int> v3(5, 1);
结果如图:
迭代器区间构造
构造一个vector<char>类对象
string s1("Hello");
vector<char> v5(s1.begin(), s1.begin() + 2);
关于T()的问题
调用n个T类型构造方方法进行构造时,如果第二个参数没有给出,会用默认的T()填充,对用内置类型,T()的值都为0,自定义类型则会调用默认的构造函数,而如果该自定义类型没有默认的构造函数,程序会报错,如图:
拷贝构造函数
vector<int> v1(3, 1);
vector<int> v2(v1);//调用拷贝构造函数
二、迭代器与元素访问
迭代器
- begin&end 获取第一个数据位置的iterator,最后一个数据下一个位置的迭代器
- rbegin + rend 获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator
- cbegin、cend、crbegin、crend这四个是const类型的迭代器,可以访问const成员变量
- operator[] 通过下标访问,与at的区别是,operator[]底层通过assert处理越界,而at访问越界会抛出异常
访问方式
下标访问
vector<int> v{ 0,1,2,3,4,5 };
for (int i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
迭代器访问
可以使用auto定义变量
//auto it = v.begin();
vector<int>::iterator it = v.begin();
for (it; it != v.end(); it++)
{
cout << *it << " ";
}
反向迭代器
//auto rit = v.rbegin();
vector<int>::reverse_iterator rit = v.rbegin();
for (rit; rit != v.rend(); rit++)
{
cout << *rit << " ";
}
范围for
for (auto e : v)
{
cout << e << " ";
}
三、容量相关
- size 有效元素个数
- capacity 容量大小
- empty 判断是否为空
- resize 改变size大小
- reserve 扩容
vector扩容机制
VS2022
VS中使用的是PJ版本的STL,capacity是按1.5倍进行扩容的
g++
g++使用的是SGI版的STL,按照2倍进行扩容
四、内容修改接口
- push_back 尾插
- pop_back 尾删
- assign 重新分配
- insert 任意位置插入
- erase 任意位置删除
- swap 交换连个vector对象的空间
- clear 清空对象内容
swap的使用,在交换两个vector类对象时,尽可能使用vector类内置的swap函数,因为内置的交换函数效率更高,使用swap函数模板交换时会定义临时变量,效率较低。
五、关于vector的迭代器失效问题
什么是迭代器失效
迭代器的主要作用就是让程序不关心底层的数据结构,其底层实际就是一个指针或者对指针进行封装,在vector中,迭代器就是原生态的指针T*类型。而迭代器失效,实际就是迭代器底层对应的指针所指向的空间被销毁,而使用了一块被释放的空间,会导致程序崩溃。
会引起底层空间改变的操作,都有可能导致迭代器失效
迭代器失效验证
改变底层空间
以push_back为例:
在上面的程序中,迭代器it指向vector类对象v的起始位置,调用push_back进行尾插之后,v底层空间不够进行了扩容操作,而扩容操作的一般步骤是:开辟新空间,拷贝元素,释放旧空间;执行完这三步以后,v中的元素已经被拷贝到了新的空间,而迭代器it指向的旧空间已经被释放,再次对it进行操作时,会访问到已经释放的空间,而引起程序崩溃。
除了push_back外,resize、reserve、insert、assign、operator=这些操作都有可能导致迭代器失效。
erase引起的迭代器失效
- VS2022中
- g++
在两种编译环境中,erase删除当前位置元素后,编译器都会让指向当前位置的迭代器失效。而erase删除当前位置元素后会返回下一个位置的迭代器:
iterator erase (iterator position);
iterator erase (iterator first, iterator last);
所以解决的办法就是用it接收erase的返回值:
swap引起的迭代器失效
解决方法
迭代器失效的解决方法:在使用前,对迭代器进行重新赋值,对于上文push_back的程序作修改:
无论迭代器在何处定义,使用前都重新进行赋值,避免迭代器失效的问题。
六、动态二维数组
杨辉三角
矩阵