【C++】STL容器--vector的使用
·
目录
前言
前面介绍了【C++】STL容器–string的模拟实现详情请点击,本文继续介绍另一个STL容器–vector的使用
一、vector的介绍
- vector 是表示可变长数组的容器,他的本质是一个类模板
- vector 采用连续的一段空间来存储数据,和数组一样可以通过下标访问数据
- vector当空间不够时会实现自动扩容,在vs上扩容1.5倍(不同编译器扩容倍数不同),扩容机制采用异地扩容,再将原始数据拷贝到新空间,释放旧空间
二、vector的使用
使用vector除了包含C++的常规头文件外,还需要包含#include< vector>
1、构造函数/拷贝构造

- 构造函数有全缺省的构造,这里有一个allocator_type()参数,它是空间配置器,我们默认不传参即可
- 构造函数可以传入n个值进行初始化
- 构造函数还可以使用迭代器进行初始化构造对象
- 拷贝构造传入vector类型的对象

2、析构函数
析构函数在类对象生命周期结束时会自动调用对资源进行清理,不需要我们显示
3、operator=

- 赋值运算符重载可以对已经初始化的vector对象进行赋值运算
int main()
{
vector<int> v1(5, 7);
vector<int> v2(v1.begin() + 3, v1.end());
v2 = v1;
return 0;
}

4、begin/end/rbegin/rend

- vector迭代器和string类似,都是相通的,这里就不做过多解释,详情请点击查看string的使用,这里只演示vector< int >迭代器的使用
int main()
{
int arr[4] = { 14, 98, 112, 77 };
vector<int> v1(arr, arr + 3);
vector<int>::iterator it = v1.begin();
while (it != v1.end())
{
(*it)++;
cout << *it << " ";
++it;
}
cout << endl;
return 0;
}
结果如下,我们使用迭代器遍历了vector,并修改了vector中数据

5、operator[]、范围for、at
1. operator[]

- vector重载了[],实现了下下标访问,类似数组一样,opertor[]返回的是元素的引用,因此可以访问和修改,被const修饰的只能访问,不能修改

- 如果operator[]下标访问超出了下标范围,VS会直接断言报错(debug版本下),严格检查机制

2. 范围for
我们可以使用范围for来遍历vector,支持迭代器就支持范围for,其底层就是依赖范围迭代器实现的
3. at

- at 和[]类似可以进行下标访问,返回下标的引用,如果下标位置插入范围会抛异常,我们可以捕获异常信息,普通对象可以修改,const对象只能访问,不能修改
6、size/capacity/empty

- size:返回vector的有效数据个数
- capacity:获取容量大小
- empty:判断vector是否为空,为空返回true,为假返回false

7、resize/reserve
1. resize

- 当resize指定的数据个数大于当前vector的有效数据个数,那么会在有效数据个数后面添加某个数(如果传入了特定值,用该值填补,没有则默认是0)直到vector有效数据个数等于resize指定的数据个数
- 如果resize的数据个数小于当前vector的有效数据个数,那么会将vector有效数据个数减少到resize指定的个数,且vector的容量大小不会改变
int main()
{
int arr[7] = { 14, 98, 112, 77 , 12, 45, 74 };
vector<int> v1(arr, arr + 7);
v1.resize(10);
for (auto& e : v1)
{
cout << e << " ";
}
cout << endl;
vector<int> v2(arr, arr + 7);
cout << v2.capacity() << endl;
v2.resize(2);
for (auto& e : v2)
{
cout << e << " ";
}
cout << endl;
cout << v2.capacity() << endl;
return 0;
}

2. reserve

- reserve一次性扩容开空间,reserve使用的情况一般是我们预先知道我们要开多少空间,使用reserve提起开辟出来,这样就不会因为有效数据的插入而频繁增容
- 如果你与开的空间小于当前vector的空间,那么当前空间保持不变,不会缩容

8、push_back/pop_back
- 在vector数据尾部插入一个数据

- 删除vector尾部的数据


9、insert/erase
1. insert

- insert可以在迭代器某个位置插入一个数据,但是涉及到扩容问题可能会导致迭代器失效,返回新插入的迭代器的位置
- insert可以在迭代器某个位置插入n个数据
- insert可以在迭代器某个位置插入另一个迭代器区间的数据
int main()
{
int arr[7] = { 14, 98, 112, 77 , 12, 45, 74 };
vector<int> v1(arr, arr + 7);
v1.insert(v1.begin(), 111);
for (auto& e : v1)
{
cout << e << " ";
}
cout << endl;
vector<int> v2(arr, arr + 7);
v2.insert(v2.end(), 5, 777);
for (auto& e : v2)
{
cout << e << " ";
}
cout << endl;
vector<int> v3(arr, arr + 7);
vector<int> v4(4, 7);
v3.insert(v3.end()- 2, v4.begin(), v4.begin() + 3);
for (auto& e : v3)
{
cout << e << " ";
}
return 0;
}

2. erase

- erase删除某个迭代器位置的值,并返回该迭代器,同时也可以删除某个迭代器区间(左闭右开)的值
int main()
{
int arr[7] = { 14, 98, 112, 77 , 12, 45, 74 };
vector<int> v1(arr, arr + 7);
for (auto& e : v1)
{
cout << e << " ";
}
cout << endl;
v1.erase(v1.begin());
for (auto& e : v1)
{
cout << e << " ";
}
cout << endl;
vector<int> v2(arr, arr + 7);
v2.erase(v2.begin(), v2.end() - 1);
for (auto& e : v2)
{
cout << e << " ";
}
cout << endl;
return 0;
}

10、swap
- 交换两个vector的内容,和string的swap一样,vector的交换也是交换指针指向的空间,而不是进行多次拷贝构造

11、clear
- 清空vector里面的有效数据

三、initializer_list

使用花括号传入几个相同类型的值,返回类型就是initializer_list<类型>
-
比如:
auto il = {10, 20, 30},那么il就是initializer_list< int >
-
遍历该类型可以使用迭代器,也可以使用范围for,但是我们一般使用范围for

-
C++11中vector的构造中新增了一个
vector (initializer_list<value_type> il,const allocator_type& alloc = allocator_type());,我们可以利用initializer_list来进行初始化


更多推荐




所有评论(0)