详解c++---vector介绍

news2025/1/20 3:42:21

这里写目录标题

  • 什么是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<T>,这里大家就不用管,他已经给了缺省参数而且这句的用处是创建一个内存池用来加快内存分配的速度,接下来我们再来看看vector有哪些不同类型的构造函数:
在这里插入图片描述
第一种:

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

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

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

上面代码的运行结果如下:
在这里插入图片描述
第二种:

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;
}

这段代码的运行结果为:
在这里插入图片描述
那这个时候就有小伙伴就要问了,既然都是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();
	}
}

这段代码的运行结果为:
在这里插入图片描述
第三种形式:

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();
	}
}

代码的运行结果如下:
在这里插入图片描述
第四种形式:

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();
	}
}

这段代码的运行结果为:
在这里插入图片描述
那么这就是构造函数的四种不同的形式希望大家能够理解。

reserve

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

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;
}

代码的运行结果如下:
在这里插入图片描述

vector数据插入

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

push_back

首先来看看这个函数的英文介绍:
在这里插入图片描述
在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();
	}
}

代码的运行结果为:
在这里插入图片描述

insert

上面的函数只能在对象的尾部进行插入数据,并且每使用一次这个函数只能插入一个数据,那这里的insert函数则可以实现在对象的任意位置插入数据,并且一下子可以插入多个数据该函数的形式如下:
在这里插入图片描述
这里的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();
	}
}

代码的运行结果如下:
在这里插入图片描述

resize

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

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();
	}
}

这段代码的运行结果为:
在这里插入图片描述
我们可以看到当长度变大之后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();
	}
}

代码的运行结果如下:
在这里插入图片描述
我们看到这里的内容确实发生了修改数据变小了。

assign

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

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;
}

这段代码的运行结果如下:
在这里插入图片描述
第二种就是通过给定的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;
}

这段代码的运行结果如下:
在这里插入图片描述

vector数据的删除

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

pop_back

这个函数就是实现尾删,这个删除就是将vector中的最后一个数据删除,我们看可以看看这个函数的介绍:
在这里插入图片描述
这个函数没有任何的参数,我们可以通过下面的代码来看看该函数的使用:

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();
	}
}

运行的结果为:
在这里插入图片描述

erase

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

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();
	}	
}

我们将这个代码运行一下就可以看到第三个元素被删除了:
在这里插入图片描述
其次就是一段元素的删除:

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();
	}
}

这里是一段数据的删除,这里的一段所表示的意思就是将第一个元素和最后一个元素保留其他元素都删除,我们可以看看这段代码的运行结果:
在这里插入图片描述
这就是该函数的使用希望大家能够理解。

clear

上面是一段数据或者一个数据的删除,那么这里的clear函数是将全部的数据删除,我们可以看看这个函数的介绍:
在这里插入图片描述
这个函数的使用也非常的简单毕竟他没有参数嘛,我们可以看看下面的代码来看看这个函数的作用:

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;
}

该代码的运行结果为:
在这里插入图片描述

vector性质查看

size

这个函数的作用是查看当前对象含有的元素个数:
在这里插入图片描述
可以看看下面的代码:

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;
}

在这里插入图片描述

capacity

该函数作用是查看该对象的容量
在这里插入图片描述

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;
}

在这里插入图片描述

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,我们这里可以看看这段代码的运行结果:
在这里插入图片描述
当我们不往对象中插入数据时,这个函数的返回值就是1,可以看看下面的代码:

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

这段代码的运行结果如下:
在这里插入图片描述

max_size

这个函数真没啥用,他的意义就是告诉你该对象最多能够容乃多少个元素,我们可以看看该函数的介绍和使用的代码:
在这里插入图片描述

对应的代码为:

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

代码的运行结果为:

在这里插入图片描述

vector元素修改

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

operator[ ]

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

我们可以通过下面的代码来看看该函数的操作:

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();
	}
}

代码的运行结果如下:

在这里插入图片描述
当我们给的下标不合法的时候再使用[ ]就会报错:

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();
	}
}

在这里插入图片描述

at

这个函数的作用和operator[ ]的作用是一样的,唯一的区别就在于对于不合法的下标at会抛异常不会报错而[ ]会报错,我们来看看这个函数的介绍:
在这里插入图片描述
我们来看看下面的代码:

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();
	}
}

这段代码的运行结果如下:
在这里插入图片描述

front

在这里插入图片描述
该函数的作用就是返回vector中的第一个元素,我们可以根据这个函数来修改和打印对应的数据。

back

在这里插入图片描述
该函数的作用就是返回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();
}

代码的运行结果如下:
在这里插入图片描述

vector其他函数

operator=

这个就是赋值重载,将一个vector对象的内容赋值给另一个vector对象,我们可以看看该函数的介绍:
在这里插入图片描述
该函数的使用如下:

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();
	}
}

代码的运行结果如下:
在这里插入图片描述

swap

在vector对象当中有两个swap函数,我们来看看这两个不同的swap函数对应的介绍:
在这里插入图片描述
第二个:
在这里插入图片描述
而且在我们的库中也有一个swap函数:
在这里插入图片描述
那这里有两个问题,为什么库中会有两个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。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/155213.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入浅出Cookie、Session、Token:背后的技术原理

目录 简介 . 网站交互体验升级 1.1 无状态的 HTTP 协议 1.2 解决之道 2. Cookie方案 2.1 Cookie 定义和作用 2.2 服务端创建 Cookie 2.4 存在的问题 3. Session 方案 3.1 Session 机制的概念 3.2 简单的交互流程 3.3 Session 的实现方式 3.4 存在的问题 4. Token…

【微服务】Nacos 认证机制

目录 一、背景 二、需求 三、方案 1、安全架构选型 2、会话管理 2.1、会话选型 2.2、Session 登录流程 2.3、Token 登录流程 2.4、jwt 框架选型 2.5、会话超时 3、SSO 支持 4、UI设计 5、接口设计 6、数据库表设计 6.1、user表 6.2、roles表 7、Filter 拦截请求…

C++ —— 模板的基本概念和使用

目录 1.函数模板是什么 1.1函数模板的基本概念 1.2函数模板的基本使用 1.3函数模板的特化 1.4非类型模板参数 2.类模板是什么 2.1类模板的基本使用 2.2非类型模板参数 2.3类模板的特化 2.4模板特化后的优先级 3.函数模板不要分离编译 1.函数模板是什么 模板是一种…

python和MySQL的基础使用和数据的插入导出

一.基础使用第三方库pymysql除了使用图形化工具以外&#xff0c;我们也可以使用编程语言来执行SQL从而操作数据库。在Python中&#xff0c;使用第三方库:pymysql来完成对MySQL数据库的操作。安装创建到MySQL的数据库链接具体代码如下from pymysql import Connect #获取到MySQL数…

LVS+Keepalived+Nginx宏观整体结构与关键问答

视频链接&#xff1a;4-2 为什么要使用 LVS Nginx&#xff1f;_哔哩哔哩_bilibili ———————————————————————————————————————————————————————— 1. 问题&#xff1a; 为什么要使用LVS Nginx&#xff1f;&#xf…

C语言刮刮乐(掩码图的范例)

程序简介 这个程序模拟了刮刮乐的刮卡操作&#xff0c;按下鼠标左键并移动可以刮开刮卡层。 刮卡操作是通过掩码图实现的&#xff0c;一张隐藏的待刮开背景图&#xff0c;一张掩码图。 刮卡的时候&#xff0c;是在黑色的掩码图上画线&#xff0c;显示的时候&#xff0c;通过…

官方正品 | Ultralytics YOLOv8算法来啦(尖端SOTA模型)

&#x1f680;&#x1f680;&#x1f680;卷王之王 | Ultralytics YOLOv8 算法来啦&#xff01;&#xff01;✨✨✨ 一、前言简介 &#x1f384;&#x1f388; &#x1f4da; 代码地址&#xff1a;卷王之王 | YOLOv8代码下载地址 &#x1f4da; 详细文档&#xff1a;https://…

代码随想录算法训练营第十四天字符串 java :二叉树理论基础 144前序遍历 145后续遍历94 中序遍历

系列文章目录 第十一天笔记 文章目录系列文章目录前言1、二叉树理论基础1.1二叉树的种类1.1 如何区分二叉树的遍历方式1.2 如何定义二叉树节点2 递归遍历2.1**前序遍历 AC代码**2.2**后序遍历 AC代码**2.3 **中序遍历 AC代码**3 迭代法4 层次遍历总结**什么是List<List <…

组态王软件与S7-1200无线MODBUS通信方案详解

本方案是组态软件与西门子 S7-1200进行无线 MODBUS 通信的实现方法。此方案可以作为西门子 S7-1200与组态软件的无线 MODBUS 通信实例。在本方案中采用了西门子PLC专用无线通讯终端DTD434MC&#xff0c;作为实现无线通讯的硬件设备。 一、方案概述 组态王配置为标准 MODBUS 主…

基础面试问题

在Java中获取当前的工作目录System.getProperty("user.dir")public class Test {public static void main(final String[] args) {final String dir System.getProperty("user.dir");System.out.println("current dir " dir);} }获取一定范围…

Redis01之Windows版本的Redis安装配置

目录 0. 学习网址 https://www.w3cschool.cn/redis/https://www.w3cschool.cn/redis/ 1. Redis简介 2. 下载 3. 安装和配置 3.1 window(略...) 3.2 linux(CentOS) 4. Redis支持五种数据类型 5.通过命令操作redis 0. 学习网址 https://www.w3cschool.cn/redis/http…

一文搞懂CPU如何控制I/O设备

1 接口和设备&#xff1a;经典适配器模式 输入输出设备不只是一个设备。大部分输入输出设备&#xff0c;都有&#xff1a; 它的接口&#xff08;Interface&#xff09;实际的I/O设备&#xff08;Actual I/O Device&#xff09; 硬件设备并非直接接入到总线上和CPU通信&#…

UOS 录制电脑播放的音频 / 内录音频

Windows 里面有一个“立体声混音”&#xff0c;可以内录电脑播放的音频&#xff0c;而不受到外界噪音的干扰。前段时间接到反馈说 UOS 的设置里面的音频输入里面没有可以选择的设备&#xff0c;这里就稍微探索了一下&#xff0c;发现 UOS 也是可以配置内录的。这里参考了一下这…

网络基础(一)

网络基础&#xff08;一&#xff09;计算机网络背景网络发展独立模式: &#xff08;计算机之间相互独立&#xff09;网络互联: ( 多台计算机连接在一起, 完成数据共享)局域网LAN: (计算机数量更多了, 通过交换机和路由器连接在一起);广域网WAN: &#xff08;将远隔千里的计算机…

vue入门到精通(一)

一、vue简介 Vue是一款用于构建用户界面的 JavaScript 框架。 它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发用户界面。 无论是简单还是复杂的界面&#xff0c;Vue 都可以胜任。 二、vue3选项式…

Linux编译器-gcc/g++使用

目录 1. 背景知识 2. gcc如何完成 2.1 预处理(进行宏替换) 2.2 编译&#xff08;生成汇编&#xff09; 2.3 汇编&#xff08;生成机器可识别代码&#xff09; 2.4 链接&#xff08;生成可执行文件或库文件&#xff09; 3 函数库 3.1 分类 3.2 图解 4 gcc选项 1. 背景知…

开源工具系列2:Trivy

在云原生安全的场景中&#xff0c;一个常见的场景就是对漏洞和配置进行扫描&#xff0c;以发现整个 K8s 环境的安全问题。今天我们来介绍一个高效的扫描工具Trivy。 Trivy 是什么 Trivy&#xff08;tri 发音为 trigger&#xff0c;vy 发音为 envy&#xff09;是一个简单而全面…

QT 学习笔记(十七)

文章目录一、多线程简介1. 基础知识2. 多线程的优缺点及注意事项二、多线程详解1. 背景案例2. 通过多线程对背景案例进行优化3. 方法一&#xff1a;多线程的创建使用&#xff08;QT 4.7 以前&#xff09;3.1 方法一的创建步骤3.2 方法一的具体实现及实现代码4. 方法二&#xff…

Android Hook之Frida安装使用

目录Frida安装安装frida-serverfrida-server配置和启动Frida Hook实例1&#xff1a;实例2&#xff1a;Frida 常用命令Frida 是一个动态检测框架&#xff0c;允许开发人员在 Windows、macOS、Linux、iOS 和 Android 上的原生应用程序中注入 JavaScript 或 Python 脚本。该框架可…

Spring复习(二)

FactoryBean FactoryBean是一个接口&#xff0c;需要创建一个类实现该接口 package com.mao.pojo;import org.springframework.beans.factory.FactoryBean;public class StudentFactoryBean implements FactoryBean {//getObject方法将对象交给Spring容器来管理Overridepubli…