目录
vector的介绍
vector的使用
vector的定义
vector iterator 的使用
vector 空间增长问题
vector 增删查改
vector 迭代器失效问题。(重点)
vector的介绍
1、 vector 是表示可变大小数组的序列容器,可以使用连续储存空间存元素,这代表可以使用下标访问容器内的元素,和数组一样但又比数组高效,体现在可以自动控制容器大小。
2、本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小 为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是 一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
使用STL的三个境界:能用,明理,能扩展 ,那么下面学习vector,我们也是按照这个方法去学习
vector的使用
vector在实际中非常的重要,在实际中我们熟悉常 见的接口就可以,下面列出了哪些接口是要重点掌握的
。
vector的定义
(constructor)
构造函数声明
|
接口说明
|
vector()
(重点)
|
无参构造
|
vector
(
size_type n, const value_type& val =value_type()
)
|
构造并初始化
n
个
val
|
vector (const vector& x);
(重点)
|
拷贝构造
|
vector (InputIterator first, InputIterator last);
|
使用迭代器进行初始化构造
|
vector iterator 的使用
iterator
的使用
|
接口说明
|
begin
+
end
(重点)
|
获取第一个数据位置的
iterator/const_iterator
, 获取最后一个数据的下一个位置
的
iterator/const_iterator
|
rbegin
+
rend
|
获取最后一个数据位置的
reverse_iterator
,获取第一个数据前一个位置的
reverse_iterator
|
// vector的迭代器
void PrintVector(const vector<int>& v)
{
// const对象使用const迭代器进行遍历打印
vector<int>::const_iterator it = v.begin();
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
vector 空间增长问题
容量空间
|
接口说明
|
size
|
获取数据个数
|
capacity
|
获取容量大小
|
empty
|
判断是否为空
|
resize
(重点)
|
改变
vector
的
size
|
reserve
(重点)
|
改变
vector
的
capacity
|
capacity
的代码在
vs
和
g++
下分别运行会发现,
vs
下
capacity
是按
1.5
倍增长的,
g++
是按
2
倍增长的
。 这个问题经常会考察,不要固化的认为,vector
增容都是
2
倍,具体增长多少是根据具体的需求定义 的。vs
是
PJ
版本
STL
,
g++
是
SGI
版本
STL
。 reserve只负责开辟空间,如果确定知道需要用多少空间,
reserve
可以缓解
vector
增容的代价缺陷问 题。resize在开空间的同时还会进行初始化,影响
size
。
vector 增删查改
vector
增删查改
|
接口说明
|
push_back
(重点)
|
尾插
|
pop_back
(重点)
|
尾删
|
find
|
查找。(注意这个是算法模块实现,不是
vector
的成员接口)
|
insert
|
在
position
之前插入
val
|
erase
|
删除
position
位置的数据
|
swap
|
交换两个
vector
的数据空间
|
operator[]
(重点)
|
像数组一样访问
|
vector 迭代器失效问题。(重点)
迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了
封装
,比如:
vector
的迭代器就是原生态指针
T*
。因此
迭代器失效,实际就是迭代器底层对应指针所指向的
空间被销毁了,而使用一块已经被释放的空间
,造成的后果是程序崩溃
(
即
如果继续使用已经失效的迭代器,
程序可能会崩溃
)
。
对于
vector
可能会导致其迭代器失效的操作有:
1.
会引起其底层空间改变的操作,都有可能是迭代器失效
,比如:
resize
、
reserve
、
insert
、
assign
、 push_back等。
#include <iostream>
using namespace std;
#include <vector>
int main()
{
vector<int> v{1,2,3,4,5,6};
auto it = v.begin();
// 将有效元素个数增加到100个,多出的位置使用8填充,操作期间底层会扩容
// v.resize(100, 8);
// reserve的作用就是改变扩容大小但不改变有效元素个数,操作期间可能会引起底层容量改变
// v.reserve(100);
// 插入元素期间,可能会引起扩容,而导致原空间被释放
// v.insert(v.begin(), 0);
// v.push_back(8);
// 给vector重新赋值,可能会引起底层容量改变
v.assign(100, 8);
/*
出错原因:以上操作,都有可能会导致vector扩容,也就是说vector底层原理旧空间被释放掉,
而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的
空间,而引起代码运行时崩溃。
解决方式:在以上操作完成之后,如果想要继续通过迭代器操作vector中的元素,只需给it重新
赋值即可。
*/
while(it != v.end())
{
cout<< *it << " " ;
++it;
}
cout<<endl;
return 0;
}
2.
指定位置元素的删除操作
-
-erase
#include <iostream>
using namespace std;
#include <vector>
int main()
{
int a[] = { 1, 2, 3, 4 };
vector<int> v(a, a + sizeof(a) / sizeof(int));
// 使用find查找3所在位置的iterator
vector<int>::iterator pos = find(v.begin(), v.end(), 3);
// 删除pos位置的数据,导致pos迭代器失效。
v.erase(pos);
cout << *pos << endl; // 此处会导致非法访问
return 0;
}
erase
删除
pos
位置元素后,
pos
位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代 器不应该会失效,但是:如果pos
刚好是最后一个元素,删完之后
pos
刚好是
end
的位置,而
end
位置是 没有元素的,那么pos
就失效了。因此删除
vector
中任意位置上元素时,
vs
就认为该位置迭代器失效 了。
从上述两个例子中可以看到:SGI STL中,迭代器失效后,代码并不一定会崩溃,但是运行结果定定不 对,如果it不在begin和end范围内,肯定会崩溃的。
迭代器失效解决办法:在使用前,对迭代器重新赋值即可。
以上就是关于vector(容器)的使用~