c++编程(12)——STL(1)vector

欢迎来到博主的专栏——c++编程
博主ID:代码小豪


前言

关于这片博客,由于博主对于STL的6大组件还处于一知半解的阶段,因此,博主会将重点放在vector的使用上,而不会详细的讲解诸如iterator,allocator等作用。

事实上,如果你想懂STL,那么6大组件是你绕不开的一点,但如果你只是想用STL(比如用STL去leetcode刷刷题)。那么只需要和我一起了解他的接口就行了。

vector

vector单词的意思是矢量,向量,但是在STL中vector容器则是一个顺序表的数据结构。可以认为是一个大小自动改变的数组。其模板是

template < class T, class Alloc = allocator<T> > class vector;

我们先从文档当中看一下模板的类型代表什么。

T是vector元素的类型
Alloc则是内存配置器,由于博主没打算细讲内存配置器,因此我们先用其缺省值
STL很细心的为我们提供了内存配置器,因此我们只用它的缺省值也能使用vector

在vector中的成员类型有以下几个

成员类型定义
value_type模板的第一个类型参数,即模板声明中的T
allocator_type模板的第二个类型参数,即vector空间配置器
reference成员的引用类型,可以理解为value_type&
difference_type代表有符号整型
size_type代表无符号整型

希望大家很记住以上这几种类型,这些类型经常用在vector的成员函数的声明中。

成员函数

构造、析构、与赋值

vector的构造函数被重载成了以下四种形式

default (1)	
explicit vector (const allocator_type& alloc = allocator_type());
fill (2)	
explicit vector (size_type n, const value_type& val = value_type(),   const allocator_type& alloc = allocator_type());
range (3)	
template <class InputIterator>   vector (InputIterator first, InputIterator last,                 const allocator_type& alloc = allocator_type());
copy (4)	
vector (const vector& x);

看着这些密密麻麻的参数,估计大伙头都大了吧,没关系,我们可以忽略参数alloc,因为这是空间配置器,我们暂时不需要为其传递参数,只使用缺省值就行,因为缺省值传递的是STL里的空间配置器,那是大神为我们编写的(笑)。

我们可以在上述构造分成四类

(1)default构造:default构造指的是在实例化对象时不传递任何参数时调用的构造函数。vector的default构造会实例化一个空的顺序表给我们。

(2)填充构造(fill),在实例化对象的时候填充n个值为val的元素,如果使用val的缺省值,那么会向vector填充n个0。

(3)范围构造(range),在实例化对象的时候传入迭代器,构造一个包含与[first,last)范围内,相同数量元素的容器,每个元素以相同的顺序从该范围内的相应元素构造。

(4)拷贝构造(copy),构造一个与x相同的vectir对象。

使用示例

    vector<int> v1;//默认构造
	vector<int> v2(4,2);//填充构造

	//先为v1插入整型1~10
	for (int i = 1; i <= 10; i++)
	{
		v1.push_back(i);
	}

	vector<int> v3(v1.begin(),v1.end());//迭代器构造
	vector<int> v4(v3);//拷贝构造,构造一个和v3相同元素的vector

析构函数则没有太多需要说明的,因为vector设计的析构函数不需要传入参数,而且当对象生命周期到了以后会自动调用析构,因此不太需要用户在这方面构思太多。

赋值

vector& operator= (const vector& x);

赋值函数并没有重载其他参数,调用赋值函数时,只需要传入要赋值的vector对象即可,operator=会将x的内容传入到容器当中,替换掉原有容器的数据,并且将容器的size修改成符合的数据。

v1 = v2;//operator=

iterator

vectir的迭代器有四种类型,分别为

  1. iterator,正向迭代器
  2. const_iterator ,定值正向迭代器
  3. reverse_iterator ,反向迭代器
  4. const_reverse_iterator 定值反向迭代器

定值迭代器是不能修改数据的迭代器,而反向迭代器则会从后向前迭代。

vector的接口有8种,实际上掌握四种即可。

iterator begin();
const_iterator begin() const;//begin的重载版本
iterator end();
const_iterator end() const;//end的重载版本
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;//rbegin的重载版本
reverse_iterator rend();
const_reverse_iterator rend() const;//rend的重载版本

如果vector对象不具有常性,那么返回的迭代器则不会是定值迭代器(非const迭代器),若vector对象具有常性,那么返回的迭代器就是定值迭代器(const迭代器)。

既然他们被称为迭代器,那么最具代表的用法就是用迭代器遍历挣个数组了、

	vector<int> v1;//默认构造
	for (int i = 1; i <= 10; i++)
	{
		v1.push_back(i);
	}
	const vector<int>v2(v1);

	//非consr对象的迭代器是非const类型的
	vector<int>::iterator itb1=v1.begin();
	vector<int>::iterator ite1=v1.end();

	while (itb1 != ite1)
	{
		cout << ++(*itb1) << ' ';
		itb1++;
	}
	cout<<endl;
	
	//const对象的迭代器是const类型的
	vector<int>::const_iterator itb2 = v2.begin();
	vector<int>::const_iterator ite2 = v2.end();
	while (itb2 != ite2)
	{
		//(*ite2)++;error const_iterator不可被修改
		cout << *itb2++ << ' ';
	}
	cout << endl;
	vector<int>::reverse_iterator ritb1 = v1.rbegin();//反向迭代器
	vector<int>::reverse_iterator rite1 = v1.rend();

	while (ritb1 != rite1)//反向迭代器可以逆序遍历
	{
		cout << *ritb1++ << ' ';
	}
	cout << endl;

	vector<int>::const_reverse_iterator critb1 = v2.rbegin();
	vector<int>::const_reverse_iterator critb2 = v2.rend();
	
	while (critb1 != critb2)
	{
		cout << *critb1++ << " ";
	}

}

capacity

capacity的接口都是用来查看或修改vector当中内存信息,比如当前容量,元素个数。

size_type size() const;//返回vector容器的当前元素个数
size_type capacity() const;//返回vector容器的容量

size()和capacity()是获取vector对象的信息

    vector<int> v1;
	for (int i = 1; i <= 10; i++)
	{
		v1.push_back(i);
	}
	vector<int> v2;
	cout << v1.size() << endl;//获取v1当前的元素个数
	cout << v2.size() << endl;//获取v2当前的元素个数
	cout << v1.capacity() << endl;//获取v1的容量大小

当vector的元素个数超过容量大小时,vector会进行扩容,使扩容后的容量可以容纳当前的元素个数。

当然,我们可以用resize和recapacity对容器进行修改。

void resize (size_type n, value_type val = value_type());//修改元素个数
void reserve (size_type n);//修改容器额容量的大小

resize将vector容器的元素个数变成n个。
如果n小于vector容器的元素个数,那么vector将会保留前n个元素,将剩余元素销毁、
如果n大于vector容器的元素个数,那么会向vector插入val的值,直到vector容器的元素个数变为n。val的值默认是0
如果n的值大于capacity,那么vector容器将会进行扩容,直到vector容器可以容纳n个元素为止

vector<int> v1;//默认构造
for (int i = 1; i <= 10; i++)//向v1尾插10个元素
{
	v1.push_back(i);
}
v1.resize(2);//resize  默认用0填充,也可以指定val的值
//此时v1的元素只剩下前2个元素

recapacity则是对容器的容量进行修改。

如果n大于容器的当前容量,那么vector会进行扩容,将容量变为能容纳n为止,
如果n小于容器的容量,那么不会进行缩容。
recapacity只对容量造成修改,不会对vector的元素个数和元素进行修改。

element access

vector为我们提供了访问元素的接口。
在这里插入图片描述
除了operator[],其他的用的并不多,而且作用都是大差不差,因此这里博主就重点说明operator[]就行了。

operator[]是将下标访问符([])重载成函数了,我们在使用数组的时候经常会用到这个符号,其作用是访问某个位置的数组元素。而在vector当中,则是改为用operator[]访问容器元素。

    reference operator[] (size_type n);
    const_reference operator[] (size_type n) const;

reference是vector中的元素的引用。如果vector的元素是T类型,那么reference则是T&类型。

operator[]会为我们返回vector当中n位置的引用,但是要注意n位置必须是合法的,也就是n不能大于vector的size。

同时我们也要注意vector对象是否具有常性,如果是const修饰vector对象,那么返回的引用则是const T&。反之则是T&。

vector<int> v1;//默认构造
for (int i = 1; i <= 10; i++)
{
	v1.push_back(i);//向v1尾插10个元素
}
for (int i = 0; i < v1.size(); i++)
{
	v1[i]++;//用operator =访问元素
	cout << v1[i]<<' ';
}

modifier

通过modifier的接口可以对vector对象进行修改。
在这里插入图片描述

尾删与尾插
void push_back (const value_type& val);//尾插
void pop_back();//尾删

vector的数据结构是一个顺序表,因此push_back是在顺序表的表尾插入一个元素,而pop_back则是在顺序表的表尾删除一个元素。

	vector<int> v1;//默认构造
	for (int i = 1; i <= 10; i++)
	{
		v1.push_back(i);//向尾部插入数据
	}
	
	v1.pop_back();//删除尾部的数据
	v1.pop_back();
	v1.pop_back();
	for (auto& e : v1)
	{
		cout << e;
	}

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

插入与删除
single element (1)	
iterator insert (iterator position, const value_type& val);
fill (2)	
void insert (iterator position, size_type n, const value_type& val);
range (3)	
template <class InputIterator>    void insert (iterator position, InputIterator first, InputIterator last);

插入的函数被重载成了三种,一种在position的位置上插入一个值为val的元素,第二中则是在position上插入n个值为val的元素。

	vector<int> v1;//默认构造
	for (int i = 1; i <= 10; i++)
	{
		v1.push_back(i);
	}
	vector<int>v2(v1);

	v1.insert(v1.begin(), 5);//在表头插入一个5
	v2.insert(v2.begin()+3, 5, 6);	//在表头的后三个元素的位置插入5个6.

	for (auto& e : v1)
	{
		cout << e<<' ';
	}
	cout << endl;
	for (auto& e : v2)
	{
		cout << e << ' ';
	}

而第三种,insert()传递的参数都是iterator类型或者Inputiterator类型的迭代器。iterator我们熟悉,但是inputiterator却是一个模板的类型参数。这就意味着我们使用insert时需要实例化出模板函数

vector<int> v1;//默认构造
	for (int i = 1; i <= 10; i++)
	{
		v1.push_back(i);
	}
	vector<int>v2(v1);

	v1.insert(v1.end(), v2.begin(), v2.end());//将v2插入到v1的表头中
	for (auto& e : v1)
	{
		cout << e << ' ';
	}

删除erase()

iterator erase (iterator position);
iterator erase (iterator first, iterator last);

删除vector当中position位置的元素,或者删除从first到last范围内的所有元素。

	vector<int> v1;//默认构造
	for (int i = 1; i <= 10; i++)
	{
		v1.push_back(i);
	}
	vector<int>v2(v1);

	v1.erase(v1.begin() + 2);//删除第三个元素,表头元素加2即为表中第三个元素
	v2.erase(v2.begin()+5,v2.end());//删除v2第6个及其往后所有元素

	for (auto& e : v1)
	{
		cout << e << ' ';
	}
	cout << endl;

	for (auto& e : v2)
	{
		cout << e << ' ';
	}
  • 15
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码小豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值