详解c++---vector介绍

这里写目录标题

  • 什么是vector
    • vector的定义
    • reserve
  • vector数据插入
    • push_back
    • insert
    • resize
    • assign
  • vector数据的删除
    • pop_back
    • erase
    • clear
  • vector性质查看
    • size
    • capacity
    • empty
    • max_size
    • vector元素修改
    • operator[ ]
    • at
    • front
    • back
  • vector其他函数
    • operator=
    • swap

什么是vector

  1. vector是表示可变大小数组的序列容器。
  2. 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
  3. 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
  4. vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。
  5. 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。
  6. 与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起list和forward_list统一的迭代器和引用更好。

vector的定义

在这里插入图片描述
首先我们得知道一件事:为了让vector能够容乃各种各样不同类型的数据,我们这里就得使用模板来处理各种各样的情况,而且这里是类模板所以我们在创建vector对象的时候就得显示实例化,然后这个模板里面有这么一句话
class Alloc = allocator,这里大家就不用管,他已经给了缺省参数而且这句的用处是创建一个内存池用来加快内存分配的速度,接下来我们再来看看vector有哪些不同类型的构造函数:
详解c++---vector介绍_第1张图片
第一种:

explicit vector (const allocator_type& alloc = allocator_type());

这种构造函数只有一个参数,这个参数跟内存池有关并且还给了这个参数一个缺省值,所以对于第一种形式我们就可以认为他是一个无参初始化,这种初始化的结果就是vector对象里面什么内容都没有,我们可以看看下面的函数来了解这个构造函数的使用:

#include
#include
using namespace std;
void test1()
{
	vector<char> v1;//创建一个空顺序表用来装char类型的数据
	for (auto ch : v1)
	{
		cout << ch << endl;
	}
}
int main()
{
	test1();
	return 0;
}

上面代码的运行结果如下:
详解c++---vector介绍_第2张图片
第二种:

explicit vector (size_type n, const value_type& val = value_type(),
                 const allocator_type& alloc = allocator_type());

这种形式的构造函数有三个不同类型的参数,作为使用者我们只用关心前两个参数的意义,第一个参数的类型为:size_type通过官网我们可以查询到vector中size_type的意思是:无符号整型。
在这里插入图片描述
第二个参数的类型为const value_type,在官网中也可以找到该类型的介绍:
在这里插入图片描述
the first template parameter( T )的意思是:第一个模板参数类型 T,那也就是说当我们显示初始化的类型为int的话,这里的第二个参数就会转变为:const int &val = int (),那这个参数的意思是什么呢?首先我们知道的是:每个自定义类型都对应的构造函数,或者默认构造函数,c++中引进了模板这个概念,所以为了更好引进模板这个概念,在c++当中给每个自定义类型也创建了对应的默认构造函数,其构造的默认结果为0,我们可以通过下面的代码来验证:

int main()
{
	int a = int();
	double b = double();
	char c = char();
	cout << a << endl;
	cout << b << endl;
	printf("%d", c);
	return 0;
}

这段代码的运行结果为:
详解c++---vector介绍_第3张图片
那这个时候就有小伙伴就要问了,既然都是0的话那为什么不把缺省值改成0呢?何必要去调用构造函数呢?那么这里大家得知道一件事就是vector不仅仅能容乃内置类型的数据,他还可以容乃自定义类型的数据,如果我们把缺省值改成0的话,这个0他能初始化自定义类型吗?答案是很明显不能的,而这里的const T &val = T ()就是通过匿名对象来调用默认构造函数,然后让val指向这个匿名对象,在创建对象的时候会根据n的值在vector对象中创建n个T类型的对象,并让val来一 一初始化这几个新创建的对象,那么这就是该形式所表示的意思,我们可以通过下面的代码来进一步了解这里的使用:

class Date
{
public:
	Date(int year = 2022, int month = 11, int day = 11)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void print()
	{
		printf("year的值为:%d ", _year);
		printf("month的值为:%d ", _month);
		printf("day的值为:%d ", _day);
		printf("\n");
	}
private:
	int _year;
	int _month;
	int _day;

};
void test2()
{
	Date d1(2022, 12, 12);
	vector<Date> v1(3);
	vector<Date> v2(3,d1);
	cout << "接下来开始打印v1的内容:" << endl;
	for (auto v : v1)
	{
		v.print();
	}
	cout << "接下来开始打印v2的内容:" << endl;
	for (auto v : v2)
	{
		v.print();
	}
}

这段代码的运行结果为:
详解c++---vector介绍_第4张图片
第三种形式:

template <class InputIterator>
vector (InputIterator first, InputIterator last,
        const allocator_type& alloc = allocator_type());

这种形式就是用迭代器来初始化新创建出来的对象,这里有三个参数第一个就是迭代器开始的地方,第二个参数就是迭代器结束的地方,第三个参数不用管,那么下面就是该形式使用的方法:

void test3()
{
	vector<Date> v;
	v.push_back(Date(2018, 11, 11));
	v.push_back(Date(2019, 11, 11));
	v.push_back(Date(2020, 11, 11));
	v.push_back(Date(2021, 11, 11));
	v.push_back(Date(2022, 11, 11));
	vector<Date>::iterator it1 = v.begin()+1;
	vector<Date>v1(it1, v.end() - 1);
	for (auto v : v1)
	{
		v.print();
	}
}

代码的运行结果如下:
详解c++---vector介绍_第5张图片
第四种形式:

vector (const vector& x);

这个就是拷贝构造,创建一个对象的时候将另外一个对象的内容初始化给新创建的对象,比如说下面的代码:

void test4()
{
	vector<Date> v1;
	v1.push_back(Date(2018, 11, 11));
	v1.push_back(Date(2019, 11, 11));
	v1.push_back(Date(2020, 11, 11));
	v1.push_back(Date(2021, 11, 11));
	v1.push_back(Date(2022, 11, 11));
	vector<Date>v2(v1);
	for (auto v : v2)
	{
		v.print();
	}
}

这段代码的运行结果为:
详解c++---vector介绍_第6张图片
那么这就是构造函数的四种不同的形式希望大家能够理解。

reserve

当我们要往一个对象中插入许多数据时,对象会不停的进行扩容,而对象里面的扩容基本上都是异地扩容,所以当对象不停进行扩容的话,他的效率必定会降低很多,所以为了避免扩容我们这里就可以使用reserve函数来一次性提高对象的容量,该函数的形式如下:
详解c++---vector介绍_第7张图片
我们可以用下面的代码来看看这个函数的使用:

void test5()
{
	vector<Date> v1(5);
	cout <<"对象的长度为:" << v1.size() << endl;
	cout <<"对象的容量为:" << v1.capacity() << endl;
	v1.reserve(100);
	v1.push_back(Date(2018, 11, 11));
	cout << "修改容量和插入数据之后" << endl;
	cout << "对象的长度为:" << v1.size() << endl;
	cout << "对象的容量为:" << v1.capacity() << endl;
}

代码的运行结果如下:
详解c++---vector介绍_第8张图片

vector数据插入

当我们知道了如何创建并初始化一个对象时,我们这里就可以往这个对象插入一些我们想要的数据,那么这里的插入数据就可以用到下面这些数据:

push_back

首先来看看这个函数的英文介绍:
详解c++---vector介绍_第9张图片
在vector对象里面这个函数的作用就是往vector对象里面插入数据,我们可以通过下面的代码来了解该函数的使用:

void test6()
{
	vector<Date> v1;
	cout << "对象的长度为:" << v1.size() << endl;
	cout << "对象的容量为:" << v1.capacity() << endl;
	v1.push_back(Date(2018, 11, 11));
	v1.push_back(Date(2019, 11, 11));
	v1.push_back(Date(2020, 11, 11));
	v1.push_back(Date(2021, 11, 11));
	cout << "插入数据之后" << endl;
	cout << "对象的长度为:" << v1.size() << endl;
	cout << "对象的容量为:" << v1.capacity() << endl;
	cout << "其内容为:" << endl;
	for (auto ch : v1)
	{
		ch.print();
	}
}

代码的运行结果为:
详解c++---vector介绍_第10张图片

insert

上面的函数只能在对象的尾部进行插入数据,并且每使用一次这个函数只能插入一个数据,那这里的insert函数则可以实现在对象的任意位置插入数据,并且一下子可以插入多个数据该函数的形式如下:
详解c++---vector介绍_第11张图片
这里的position是插入的位置,const value_type& val 是你要插入的数据,参数n的作用就是插入n个数据,最后一种形式就是通过迭代器将数据插入,我们可以通过下面的代码测试一下三种不同的插入:

void test7()
{
	vector<Date> v;
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	cout << "没修改前三个对象的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	vector<Date> v1(v);
	vector<Date> v2(v);
	vector<Date> v3(v);
	vector<Date>::iterator it = v.begin();
	vector<Date>::iterator it1 = v1.begin() + 1;
	vector<Date>::iterator it2 = v2.begin() + 1;
	vector<Date>::iterator it3 = v3.begin();
	v1.insert(it1,  Date(2018, 18, 18));
	cout << "第一种插入方式之后的内容变成:" << endl;
	for (auto ch : v1)
	{
		ch.print();
	}
	v2.insert(it2,3, Date(2018, 18, 18));
	cout << "第二种插入方式之后的内容变成:" << endl;
	for (auto ch : v2)
	{
		ch.print();
	}
	v3.insert(it3, it, v.end());
	cout << "第三种插入方式之后的内容变成:" << endl;
	for (auto ch : v3)
	{
		ch.print();
	}
}

代码的运行结果如下:
详解c++---vector介绍_第12张图片

resize

这个函数也能往对象里面添加内容,但是这个函数的主要功能是修改对象的长度,当你修改的长度小于原本的长度的时候,resize会删除多余的数据,当你给的长度大于原本长度的时候,该函数会将多出来内容填充成你给的数据或者该类型的默认构造,我们来看看该函数的介绍:
详解c++---vector介绍_第13张图片
我们可以看看下面的代码来分析两种不同的情况,第一种当给的长度大于原本长度的时候:

void test8()
{
	vector<Date> v;
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	cout << "对象的长度为:" << v.size() << endl;
	cout << "对象的容量为:" << v.capacity() << endl;
	cout << "对象的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	v.resize(7);
	cout << "修改之后对象的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
}

这段代码的运行结果为:
详解c++---vector介绍_第14张图片
我们可以看到当长度变大之后resize会自动的将多出来的内存填补上去,这里多出来了三个所以就填补了三个,而我们没有传对应的值所以这里用的就Date的默认构造来进行填补,我们再来看看第二种情况:当修改的长度小于原本的长度的时候:

void test8()
{
	vector<Date> v;
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	cout << "对象的长度为:" << v.size() << endl;
	cout << "对象的容量为:" << v.capacity() << endl;
	cout << "对象的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	v.resize(7);
	cout << "修改之后对象的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	cout << "将长度缩小之后:" << endl;
	v.resize(2);
	for (auto ch : v)
	{
		ch.print();
	}
}

代码的运行结果如下:
详解c++---vector介绍_第15张图片
我们看到这里的内容确实发生了修改数据变小了。

assign

首先来看看这个函数的介绍:
详解c++---vector介绍_第16张图片
这个函数的作用就是将对象原来的内容全部清空,将你给的内容填入到该对象的空间里面去,这里的内容填充有两种形式,一个是通过迭代器来进行填充比如说下面的代码:

void test9()
{
	vector<Date> v;
	v.reserve(10);
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	v.push_back(Date(2022, 22, 22));
	cout << "修改之前的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	cout << "修改之前的长度为:" << endl;
	cout << v.size() << endl;
	cout << "修改之前的容量为:" << endl;
	cout << v.capacity() << endl;
	vector<Date> v1;
	v1.push_back(Date(2017, 17, 17));
	v1.push_back(Date(2017, 17, 17));
	v1.push_back(Date(2017, 17, 17));
	v1.push_back(Date(2017, 17, 17));
	v1.push_back(Date(2017, 17, 17));
	v1.push_back(Date(2017, 17, 17));
	v1.push_back(Date(2017, 17, 17));
	vector<Date>::iterator it1 = v1.begin();
	v.assign(it1,v1.end());
	cout << "修改之后的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	cout << "修改之后的长度为:" << endl;
	cout << v.size() << endl;
	cout << "修改之后的容量为:" << endl;
	cout << v.capacity() << endl;
}

这段代码的运行结果如下:
详解c++---vector介绍_第17张图片
第二种就是通过给定的n和内容来将该内容填充n次,比如说下面的代码:

void test9()
{
	vector<Date> v;
	v.reserve(10);
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	v.push_back(Date(2022, 22, 22));
	cout << "修改之前的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	cout << "修改之前的长度为:" << endl;
	cout << v.size() << endl;
	cout << "修改之前的容量为:" << endl;
	cout << v.capacity() << endl;
	vector<Date> v1;
	v.assign(3, Date(2018, 8, 17));
	cout << "修改之后的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	cout << "修改之后的长度为:" << endl;
	cout << v.size() << endl;
	cout << "修改之后的容量为:" << endl;
	cout << v.capacity() << endl;
}

这段代码的运行结果如下:
详解c++---vector介绍_第18张图片

vector数据的删除

上面的函数是往对象里面填充数据,既然有数据的填充那么与之对应的就有数据的删除,这里的删除就可以用到下面的函数:

pop_back

这个函数就是实现尾删,这个删除就是将vector中的最后一个数据删除,我们看可以看看这个函数的介绍:
详解c++---vector介绍_第19张图片
这个函数没有任何的参数,我们可以通过下面的代码来看看该函数的使用:

void test10()
{
	vector<Date> v;
	v.reserve(10);
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	v.push_back(Date(2022, 22, 22));
	cout << "修改之前的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	cout << "修改之前的长度为:" << endl;
	cout << v.size() << endl;
	cout << "修改之前的容量为:" << endl;
	cout << v.capacity() << endl;
	v.pop_back();
	cout << "使用一次pop_back之后的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	v.pop_back();
	cout << "使用二次pop_back之后的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
}

运行的结果为:
详解c++---vector介绍_第20张图片

erase

pop_back的功能是将尾部的数据删除,并且使用一次只能删除一个数据,而erase函数则可以做到在vector对象中的任意位置删除指定元素或者删除一段区间的元素,下面是该函数的介绍:
详解c++---vector介绍_第21张图片
我们可以通过下面的代码来了解一下这个函数的使用,首先是定点元素的删除:

void test11()
{
	vector<Date> v;
	v.reserve(10);
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	v.push_back(Date(2022, 22, 22));
	cout << "修改之前的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	vector<Date>::iterator it1 = v.begin();
	v.erase(it1 + 2);
	cout << "修改之后的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}	
}

我们将这个代码运行一下就可以看到第三个元素被删除了:
详解c++---vector介绍_第22张图片
其次就是一段元素的删除:

void test11()
{
	vector<Date> v;
	v.reserve(10);
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	v.push_back(Date(2022, 22, 22));
	cout << "修改之前的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	vector<Date>::iterator it1 = v.begin();
	v.erase(it1+1,v.end()-1);
	cout << "修改之后的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
}

这里是一段数据的删除,这里的一段所表示的意思就是将第一个元素和最后一个元素保留其他元素都删除,我们可以看看这段代码的运行结果:
详解c++---vector介绍_第23张图片
这就是该函数的使用希望大家能够理解。

clear

上面是一段数据或者一个数据的删除,那么这里的clear函数是将全部的数据删除,我们可以看看这个函数的介绍:
详解c++---vector介绍_第24张图片
这个函数的使用也非常的简单毕竟他没有参数嘛,我们可以看看下面的代码来看看这个函数的作用:

void test11()
{
	vector<Date> v;
	v.reserve(10);
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	v.push_back(Date(2022, 22, 22));
	cout << "修改之前的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	cout << "修改之前的长度为:" << endl;
	cout << v.size() << endl;
	cout << "修改之前的容量为:" << endl;
	cout << v.capacity() << endl;
	v.clear();
	cout << "修改之后的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	cout << "修改之后的长度为:" << endl;
	cout << v.size() << endl;
	cout << "修改之后的容量为:" << endl;
	cout << v.capacity() << endl;
}

该代码的运行结果为:
详解c++---vector介绍_第25张图片

vector性质查看

size

这个函数的作用是查看当前对象含有的元素个数:
详解c++---vector介绍_第26张图片
可以看看下面的代码:

void test12()
{
	vector<Date> v;
	v.reserve(10);
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	v.push_back(Date(2022, 22, 22));
	cout << "该对象的长度为:" << endl;
	cout << v.size() << endl;
}

详解c++---vector介绍_第27张图片

capacity

该函数作用是查看该对象的容量
详解c++---vector介绍_第28张图片

void test12()
{
	vector<Date> v;
	v.reserve(10);
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	v.push_back(Date(2022, 22, 22));
	cout << "该对象的长度为:" << endl;
	cout << v.size() << endl;
	cout << "该对象的容量为:" << endl;
	cout << v.capacity() << endl;
}

详解c++---vector介绍_第29张图片

empty

该函数的作用是查看该对象的内容是否为空,如果为空的话这个函数

void test12()
{
	vector<Date> v;
	v.reserve(10);
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	v.push_back(Date(2022, 22, 22));
	cout << "该对象是否为空:";
	cout << v.empty();
}

因为我们这个对象含有元素,所以这里的empty的返回值就是0,我们这里可以看看这段代码的运行结果:
详解c++---vector介绍_第30张图片
当我们不往对象中插入数据时,这个函数的返回值就是1,可以看看下面的代码:

void test12()
{
	vector<Date> v;
	v.reserve(10);
	cout << "该对象是否为空:";
	cout << v.empty();
}

这段代码的运行结果如下:
详解c++---vector介绍_第31张图片

max_size

这个函数真没啥用,他的意义就是告诉你该对象最多能够容乃多少个元素,我们可以看看该函数的介绍和使用的代码:
详解c++---vector介绍_第32张图片

对应的代码为:

void test12()
{
	vector<Date> v;
	v.reserve(10);
	cout << "该对象是否为空:";
	cout << v.empty()<<endl;
	cout << "该对象最多容乃多少个元素";
	cout << v.max_size()<<endl;
}

代码的运行结果为:

详解c++---vector介绍_第33张图片

vector元素修改

有时候我们要对vector中某个位置的元素进行修改,那么这里我们就可以使用下面的函数来对其内容进行修改:

operator[ ]

因为vector存储数据的方式是在一段连续的空间进行存储,所以在vector中我们将操作符[ ]进行了重载,使其[ ]可以像数组那样通过下标来获取对应的元素和修改对应的元素,我们可以看看该重载的介绍:
详解c++---vector介绍_第34张图片
我们可以通过下面的代码来看看该函数的操作:

void test13()
{
	vector<Date> v;
	v.reserve(10);
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	v.push_back(Date(2022, 22, 22));
	cout << "修改之前的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	v[1] = Date(2018, 18, 18);
	v[2] = Date(2018, 18, 18);
	v[3] = Date(2018, 18, 18);
	cout << "修改之后的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
}

代码的运行结果如下:

详解c++---vector介绍_第35张图片
当我们给的下标不合法的时候再使用[ ]就会报错:

void test13()
{
	vector<Date> v;
	v.reserve(10);
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	v.push_back(Date(2022, 22, 22));
	cout << "修改之前的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	v[5] = Date(2018, 18, 18);
	cout << "修改之后的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
}

详解c++---vector介绍_第36张图片

at

这个函数的作用和operator[ ]的作用是一样的,唯一的区别就在于对于不合法的下标at会抛异常不会报错而[ ]会报错,我们来看看这个函数的介绍:
详解c++---vector介绍_第37张图片
我们来看看下面的代码:

void test14()
{
	vector<Date> v;
	v.reserve(10);
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	v.push_back(Date(2022, 22, 22));
	cout << "修改之前的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
	v.at(1) = Date(2018, 18, 18);
	v.at(2) = Date(2018, 18, 18);
	v.at(3) = Date(2018, 18, 18);
	cout << "修改之后的内容为:" << endl;
	for (auto ch : v)
	{
		ch.print();
	}
}

这段代码的运行结果如下:
详解c++---vector介绍_第38张图片

front

详解c++---vector介绍_第39张图片
该函数的作用就是返回vector中的第一个元素,我们可以根据这个函数来修改和打印对应的数据。

back

详解c++---vector介绍_第40张图片
该函数的作用就是返回vector中的最后一个元素,我们可以根据这个函数来修改和打印对应的数据。
我们可以通过下面的代码来看看上面两个函数的使用:

void test15()
{
	vector<Date> v;
	v.reserve(10);
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	v.push_back(Date(2022, 22, 22));
	v.front().print();
	v.back().print();
	v.front() = Date(2018, 18, 18);
	v.back() = Date(2023, 1, 1);
	v.front().print();
	v.back().print();
}

代码的运行结果如下:
详解c++---vector介绍_第41张图片

vector其他函数

operator=

这个就是赋值重载,将一个vector对象的内容赋值给另一个vector对象,我们可以看看该函数的介绍:
详解c++---vector介绍_第42张图片
该函数的使用如下:

void test16()
{
	vector<Date> v;
	v.reserve(10);
	v.push_back(Date(2017, 17, 17));
	v.push_back(Date(2019, 19, 19));
	v.push_back(Date(2020, 20, 20));
	v.push_back(Date(2021, 21, 21));
	v.push_back(Date(2022, 22, 22));
	vector<Date> v1;
	v1 = v;
	for (auto ch : v1)
	{
		ch.print();
	}
}

代码的运行结果如下:
详解c++---vector介绍_第43张图片

swap

在vector对象当中有两个swap函数,我们来看看这两个不同的swap函数对应的介绍:
详解c++---vector介绍_第44张图片
第二个:
详解c++---vector介绍_第45张图片
而且在我们的库中也有一个swap函数:
详解c++---vector介绍_第46张图片
那这里有两个问题,为什么库中会有两个swap函数?为什么算法库中提供了swap函数,在vector中还要自己写swap函数呢?原因很简单,库中提供的swap函数的实现方法会造成三次深拷贝,这样的话会导致效率降低,所以我们vector就自己提供了一个swap函数,那为什么要写两个呢?答案也很简单因为有些使用使用着容易把swap函数的形式写错,如果是这样的话:
在这里插入图片描述
我们调用swap函数应该是这样:

std::vector<int> foo (3,100);  
std::vector<int> bar (5,200);   
foo.swap(bar);

而很多小伙伴会写成这样:

swap(foo,bar);

这样写的话调用的就是算法库中的swap所以为了防止有小伙伴写错了形式而调用了效率更低的swap我们的库就给了一个形式
在这里插入图片描述
这样的话就算你写错了,调用得分也是效率更高的swap。

你可能感兴趣的:(c++详解,c++,数据结构)