详解STL——vector容器

vector简介

1.vector是可以改变大小的数组的的序列容器。
2.vector和数组一样,对元素使用连续的存储空间,可以使用指向其元素的常规指针上的偏移量来访问它们的元素。
3.vector和一般数组不同的是,vector的大小能够动态变化,容器会自动扩容存储空间。
4.vector使用一个动态分配的连续存储空间来存储元素。在插入新元素时存储空间可能需要重新分配,以便扩大容量,这意味着分配一个新存储空间要将所有元素移动到其中,就处理时间而言,这是一项相对昂贵的任务,因此,向量不会在每次插入新元素时扩容
5.vector容器可以分配一些额外的存储空间以适应可能的增长,因此容器的实际容量可能大于需要的存储容量
6.vector与一般数组相比,前者消耗更多的内存,以换取管理存储和高效方式动态增长的能力。
7.与其他动态序列容器(deques、list和forward_list)相比,vector可以非常高效地访问其中的元素,并比对高效地从其末尾添加或删除元素。对于涉及在末尾以外位置的插入或删除元素的操作,其性能比其他操作差,迭代器和引用的一致性也不如list和forward_list。

vector的常用构造函数

构造函数重载功能介绍
vector();默认构造函数
vector(size_type count);构造拥有count个默认插入的T实例的容器
vector(size_type count,const T& value = T());构造拥有count个有数值是value的元素的容器
vector(InputIt first,InputIt last);构造拥有范围 [first,last) 内容的容器
演示1:vector();
vector<int> veca;

在这里插入图片描述

可以看到使用默认构造函数时,内存适配器的三个指针都是没有初始化的,可以像理解类一样,理解为创建了一个空间但是还没有实例化。

演示2:vector(size_type count);
vector<int> vecb(5);

在这里插入图片描述

这种构造方法构造了5个默认的0元素,并且能够看到三个指针存放了相应的地址。

演示3:vector(size_type count,const T& value = T());
vector<int> vecc(5,233);

在这里插入图片描述

构造出来的5个元素都被初始化为233

演示4:vector(InputIt first,InputIt last);
	int arr[] = { 12,23,34,45,56,67,78,89,90,100 };
	int n = sizeof(arr) / sizeof(arr[0]);
	vector<int> vecd(arr, arr + n);

在这里插入图片描述

使用范围去构造,arr对应地址下的元素能够得到,arr+n对应地址下的元素不能够得到

演示5:C11下的一些构造方法

C11特性下,以下构造方法也可以

	vector<int> vece = {12,23,34,45,56,67,78,89,90,100};
	vector<int> vecf {12,23,34,45,56,67,78,89,90,100};

在这里插入图片描述在这里插入图片描述

vector的迭代器

迭代器是一个变量,是容器和算法之间的“桥梁”,迭代器可以指向容器中的某个元素,通过迭代器就可以读写它指向的元素,可以将它理解为一种指针

迭代函数功能介绍
iterator begin()返回指向初始位置的迭代器
iterator end()返回指向末尾位置的迭代器
reverse_iterator rbegin()返回指向末尾位置的逆向迭代器
reverse_iterator rend()返回指向初始位置的逆向迭代器
图示

在这里插入图片描述

演示1:begin() end()
	vector<int> vec = { 12,23,34,45,56,67,78,89,90,100 };
	vector<int>::iterator it = vec.begin();
	for (;it < vec.end();++it)
	{
		cout << *it << " ";
	}

迭代器结果如下:

在这里插入图片描述

演示2:rbegin() rend()
	vector<int> vec = { 12,23,34,45,56,67,78,89,90,100 };
	vector<int>::reverse_iterator it = vec.rbegin();
	for (;it < vec.rend();++it)
	{
		cout << *it << " ";
	}

逆迭代器结果如下:

在这里插入图片描述

vector的容量函数

容量函数功能介绍
bool empty() const检查容器是否为空
size_type size() const返回容纳的元素数
size_type max_size() const返回可容纳的最大元素数
void reserve(size_type new_cap)预留存储空间
void capacity() const返回当前存储空间能够容纳的元素数
void shrink_to_fit()通过释放未使用的内存减少内存的使用
演示1:size() capacity()
	vector<int> vec;
	for (int i = 0;i < 20;++i)
	{
		vec.push_back(i+10);
		cout << "  size:" << vec.size() << "  \tcapacity:" << vec.capacity() << endl;
	}

运行结果:

在这里插入图片描述

可以看到size的大小是由元素的个数决定的,而容量capacity并不是每次都会增加,而是当有需要的时候增加一定的数量

演示2:reserve()
	vector<int> vec;
	vec.reserve(100);
	cout << "  size:" << vec.size() << "  \tcapacity:" << vec.capacity() << endl;

运行结果:

在这里插入图片描述

容器中元素个数为0,容量为100;

演示3:max_size()
	vector<int> vec_int;
	vector<double> vec_double;
	cout << "int:" << vec_int.max_size() << endl;
	cout << "double" << vec_double.max_size() << endl;

运行结果:

在这里插入图片描述

那么上面两个数是如何得来的?因为 int 占4个字节,double 占8个字节,所有2的32次方分别除4和除8就可以得出了

在这里插入图片描述

演示4:shrink_to_fit()
	vector<int> vec;
	for (int i = 0;i < 100;++i)
	{
		vec.push_back(i);
	}
	cout << "  size:" << vec.size() << "  \tcapacity:" << vec.capacity() << endl;
	vec.shrink_to_fit();
	cout << "  size:" << vec.size() << "  \tcapacity:" << vec.capacity() << endl;

首先我先往容器里面加入100个元素,加入后,元素个数一定是小于或者等于容量的,然后使用shrink_to_fit()这个函数后,会怎么样呢?下面是运行结果:

在这里插入图片描述

可以看到,容量和元素个数相等了,该函数把多余的空间释放了

vector的修改器

修改器功能
void clear()清楚容器内的所有元素
iterator insert(const_iterator p, const T& x)插入元素x
iterator insert(const_iterator p, const size_type n, const T& x)在p前插入n个x
iterator insert(const_iterator p, Iter _F, Iter _L)在p前插入来自范围[_F,_L]的元素
iterator insert(const_iterator p, initializer_list<_Ty> ls)在p前插入来自initializer_list 的元素
iterator erase(const_iterator p)移出位于 p 的元素
iterator erase(const_iterator _F, const_iterator _L)移出范围 [_F, _L] 的元素
void push_back(const T& Val)将元素Val添加到容器末尾
void pop_back()移出末尾元素
void resize(const size_type Newsize)改变容器中可存储元素的个数
void resize(const size_type Newsize, const T& x)改变容器中可存储元素为Newsize个并赋值为x
void swap(vector& Right)交换内容
演示1:insert(const_iterator p, const T& x)
	vector<int> vec = { 12,23,34,45,56 };
	vector<int>::iterator it = vec.begin();
	vec.insert(it, 10);
	Print_Forward(vec);//顺序打印函数

运行结果:

在这里插入图片描述

看到10已经被插入到第一个位置上了

演示2:insert(const_iterator p, const size_type n, const T& x)
	vector<int> vec = { 12,23,34,45,56 };
	vector<int>::iterator it = vec.begin();
	vec.insert(it + 1, 5, 10);
	Print_Forward(vec);

运行结果:

在这里插入图片描述

迭代器+1后,位置移动到元素23原本的位置,然后插入5个10,然后打印出来

演示3:insert(const_iterator p, Iter _F, Iter _L)
	int arr[] = { 1,2,3,4,5,6,7,8 };
	int n = sizeof(arr) / sizeof(arr[0]);
	vector<int> vec = { 12,23,34,45,56 };
	vector<int>::iterator it = vec.begin();
	vec.insert(it, arr,arr + n);
	//vec.insert(it, { 1,2,3,4,5 });这种写法同样正确,在一些场景下更加方便
	Print_Forward(vec);

运行结果

在这里插入图片描述

演示4:erase(const_iterator p)
	vector<int> vec = { 12,23,34,45,56, 67,78,89,90 };
	vector<int>::iterator it = vec.begin();
	vec.erase(it);
	Print_Forward(vec);

运行结果:

在这里插入图片描述

演示5:erase(const_iterator _F, const_iterator _L)
	vector<int> vec = { 12,23,34,45,56, 67,78,89,90 };
	vector<int>::iterator it = vec.begin();
	vec.erase(it,it + 3);
	Print_Forward(vec);

运行结果:

在这里插入图片描述

演示6:push_back(const T& Val) pop_back()
	vector<int> vec = { 12,23,34,45,56, 67,78,89,90 };
	vector<int>::iterator it = vec.begin();
	vec.push_back(100);
	Print_Forward(vec);
	vec.pop_back();
	Print_Forward(vec);

运行结果:

在这里插入图片描述

vector的元素访问

元素访问功能
_Ty& at(const size_type _Pos);访问指定的元素,同时进行越界检查
_Ty& operator [](const size_type _Pos);访问指定的元素,同时进行越界检查
_Ty& front();访问第一个元素
_Ty& back();访问最后一个元素
_Ty& data();返回指向第一个元素的指针
演示1:_Ty& at(const size_type _Pos); _Ty& operator [](const size_type _Pos);
	vector<int> vec = { 12,23,34,45,56, 67,78,89,90 };
	for (int i = 0; i<vec.size();++i)
	{
		cout << vec.at(i) << " ";
	}
	cout << endl;
	for (int i = 0; i < vec.size();++i)
	{
		cout << vec[i] << " ";
	}
	for (int i = 0; i<vec.size() + 1;++i)
	{
		cout << vec.at(i) << " ";
	}

运行结果:

在这里插入图片描述

如果出现了越界访问,那么编译器就将会报错

在这里插入图片描述

演示2:_Ty& front(); _Ty& back(); _Ty& data();
	vector<int> vec = { 12,23,34,45,56, 67,78,89,90 };
	int x = vec.front();
	int y = vec.back();
	int* p = vec.data();

进入调试:

在这里插入图片描述

可以看到x和y的值分别对应了容器的第一个元素和最后一个元素,指针p所指向的地址和容器的第一个元素的地址相同

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值