首页 > 其他分享 >vector的使用

vector的使用

时间:2024-03-17 21:01:29浏览次数:20  
标签:const cout val v1 v2 vector 使用

前言

前两期我们对STL和string的使用进行了介绍并对string进行了模拟实现!本期我们接着来对STL的vector进行学习!

本期内容介绍

什么是vector?

vector常用的接口

什么是vector?

通过官方文档可以很清楚的看到,vector是一个可变长的顺序表!这就意味着它可以支持扩容等一系列操作!而且他是个类模板,这就意味着不和数组一样只可以存内置类型,而自定义类型也可以!!!!后面那个是内存池,暂时不管也用不到,后面会介绍~!

vector常用接口的介绍

在正式介绍前我先来介绍一下他类型的重命名!

目前就是这两个在使用时有问题!第一个是实例化参数的类型,第二个size_type就是size_t

这样干说好像没什么卵用,下面遇到例子我会专门指出的!!!

构造、拷贝构造、赋值拷贝、析构

vector<int> v;//默认构造,val不指定默认是0

vector<int> v1(10);//用n个val构造, val不指定默认是0

vector<int> v2(v1.begin() + 2, v1.end());//用迭代器区间构造

vector<int> v3(v2);//拷贝构造

注意:vector<T> v(size_t n, value_type& val)这里的 value_type& val就是T的类型的引用,如果T是内置类型未指定的话默认用其对应的0值给val引用,然后用val去构造,如果指定了指定的值被val引用,用val去初始话!如果T是自定义类型,未指定会去调用该类型的默认构造然后用该类型的引用接收,最后再利用这个引用去做赋值; 如果指定了val直接就是那个自定类型对象的别名,用val去构造!

举个例子:vector<int> v(5);不指定初始化的值,val就是0的别名,直接用5个0构造!

vector<string> v1(10, "hello'');这里是自定义类型,指定了val就是"hello"的别名,用10个val去构造;vector<string> v5(5, string("hello world"));这样也是一样的!!!

再来举个字符串的例子:

结合上面的二维数组就可以这样定义:
vector<vector<int>> vv;

可以这样来初始化二维数组:vector<vector<int>> vv(3,vector<int>(5, 1));或者

vector<vector<int>> vv(3,{1,2,3});  (这里不明白的请点击这里)!

赋值拷贝用起来很简单!就是一个对象给另一个对象赋值的!

vector<int> v1(5, 1);

vector<int> v2(10);

v2 = v1;//赋值拷贝

析构不在多比比了,清理资源释放空间~!自动调用~!

迭代器

OK这里只介绍前面的正向和反向后面C++11新增的和上面的一样不在具体介绍~!

正向

vector<int> v1(5, 2);
vector<int>::iterator it = v1.begin();
while (it != v1.end())
{
	cout << *it << " ";
	++it;
}
cout << endl;

const vector<int> v2(5, 6);
vector<int>::const_iterator cit = v2.begin();
while (cit != v2.end())
{
	cout << *cit << " ";
	++cit;
}
cout << endl;

支持迭代器必然支持范围for,我们上一期 刚调试看完汇编他就是傻瓜式的替换迭代器:

反向

vector<int> v1 = { 1,2,3,4,5 };
vector<int>::reverse_iterator it = v1.rbegin();
while (it != v1.rend())
{
	cout << *it << " ";
	++it;
}
cout << endl;

const vector<int> v2 = { 1,2,3,4,5,6,7,8 };
vector<int>::const_reverse_iterator cit = v2.rbegin();
while (cit != v2.rend())
{
	cout << *cit << " ";
	++cit;
}
cout << endl;

const和非const的区别主要还是权限的问题~!如果不修改建议使用const的!!!

注意:这里的迭代器需要指定类域的原因是模板的原因,模板参数不一样就是一个类,为了让迭代器用法统且不冲突,需要指定是哪个类的迭代器~!

容量相关

OK,我们还是一个一个的来看:

size
vector<int> v(10, 1);
cout << v.size() << endl;

resize

还是分为三种:

n < size,保留前n个,后面的都删掉(不缩容)

size < n < caapcity,尾插元素到n,如果指定了val就用指定的,否则用默认的

n > capacity,扩容到n再尾插

vector<int> v(10, 1);
for (auto e : v)
{
	cout << e << " ";
}
cout << endl;
cout << v.size() << endl;
cout << v.capacity() << endl << endl;

v.resize(5);//n < size,尾删保留前n个
for (auto e : v)
{
	cout << e << " ";
}
cout << endl;
cout << v.size() << endl;
cout << v.capacity() << endl << endl;

v.resize(7, 3);// size < n < capacity,尾插
for (auto e : v)
{
	cout << e << " ";
}
cout << endl;
cout << v.size() << endl;
cout << v.capacity() << endl << endl;

v.resize(20, 5);//n > capacity,扩容+尾插
for (auto e : v)
{
	cout << e << " ";
}
cout << endl;
cout << v.size() << endl;
cout << v.capacity() << endl;

capacity

容量上面刚刚看了,,这里不在演示!

empty

reserve

这个和在string介绍的一样!如果n大于capacity时才会扩容!其他情况不做处理, 也就是这个函数不会缩容!

vector<int> v(10, 1);
cout << v.size() << endl;
cout << v.capacity() << endl << endl;

v.reserve(20);
cout << v.size() << endl;
cout << v.capacity() << endl << endl;

v.reserve(2);
cout << v.size() << endl;
cout << v.capacity() << endl;

OK,我们也可以来验证一下扩容:

vector<int> v;
size_t end = v.capacity();
cout << end << endl;
for (size_t i = 0; i < 100; i++)
{
	v.push_back(i);
	if (end != v.capacity())
	{
		end = v.capacity();
		cout << end << endl;
	}
}

VS下是1.5倍扩!

Linux下是2倍扩:

这里还是和上期介绍的一样,如果提前知道要多少空间的话,我们可以提前开好!这样可以减少扩容的消耗!

shrink_to_fit

这个函数就是为了缩容而准备的!但是不是说你想缩到多少就多少,而是把容量缩小到size

vector<int> v = { 1,3,5,6,2,3,7 };
cout << v.size() << endl;
cout << v.capacity() << endl << endl;
	
v.reserve(100);
cout << v.size() << endl;
cout << v.capacity() << endl << endl;

v.shrink_to_fit();
cout << v.size() << endl;
cout << v.capacity() << endl;

元素访问

operator[]

有const和非const版本,还是权限问题~!非const可以修改,const不可修改~!

at的作用和operator的作用一样,这里不在演示~!

front

back

data

这个函数是返回在顺序表中的第一个元素的指针!

这个接口是C++11提供的,但是C++兼容C语言,你可以直接去取v[0]的地址~!

修改相关

push_back

pop_back

vector<int> v = { 1,2,3,4,5,6,7,8,9 };
for (auto e : v)
{
	cout << e << " ";
}
cout << endl << endl;

v.push_back(0);
for (auto e : v)
{
	cout << e << " ";
}
cout << endl << endl;

v.pop_back();
for (auto e : v)
{
	cout << e << " ";
}
cout << endl;

insert

注意:他这里的position和以前的不一样,以前是个具体的下标!这里是一个迭代器位置!

还有插入一个迭代器区间不是只可以插入当前vector同类型的!而是其他的也是可以的,因为上面也看到了他是一个模板参数!!!

void test_vector7()
{
	vector<int> v(6, 1);

	//在第一个位置插入一个0
	v.insert(v.begin(), 0);
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;

	//在4号元素的前面插入5个6
	v.insert(v.begin() + 4, 5,6);
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;

	//在2号位置插入一个迭代器区间这
	string s("hello world");
	v.insert(v.begin() + 2, s.begin(), s.end());
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;
}

erase

void test_vector8()
{
	vector<int> v = { 1,2,3,4,5 };
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;

	v.erase(v.begin() + 2);
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;

	v.erase(++v.begin(), --v.end());
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;
}

swap

这个也是交换指针的,不算法库里面的效率高~!

非常成员函数

swap

这里只介绍一个就是全局的swap和string的那个全局的一样,是为了防止用户误操作调到算法库的那个而引起拷贝,所以重载了这个,它的底层是成员函数swap实现的~!

OK,vector的常用接口就介绍到这里,好兄弟我们下期再见!!

结束语: 纵有疾风起,人生不言弃!

标签:const,cout,val,v1,v2,vector,使用
From: https://blog.csdn.net/m0_75256358/article/details/136758517

相关文章

  • Vector Quantization
    VectorQuantizationQuantization(量化)Definition:aprocessofrepresentingalarge–possiblyinfinite–setofvalueswithamuchsmallerset.WidelyUsedinLossyCompressionRepresentcertainimagecomponentswithfewerbits(compression)Withunavoidab......
  • 使用linux三剑客取ip地址
    1,使用awk命令ifconfigens33(先试用ifconfig来查看IP地址在几行几列或者使用ip-a也可以)可以看到IP地址在第二列第二行,接下来使用awk命令来取出IP地址ifconfigens33|awk'{print$2}'|awk'NR==2{print$0}'(print$2打印出第二列)(print$0打印出一整行内容)(NR等......
  • 从0到1:CTFer成长之路网上平台的使用以及docker环境配置
    1.首先安装docker(这里在kali里演示)sudosu#以root身份运行aptinstalldocker.io#安装dockersystemctlstartdocker#启动dockersystemctlenabledocker.service#将docker服务设置为开机自启docker-v#查看是否安装成功,回显版本号说明安装成功2.配置yml文件并启动ap......
  • Linux第81步_使用“互斥体”实现“互斥访问”共享资源
    1、创建MyMutexLED目录输入“cd/home/zgq/linux/Linux_Drivers/回车”切换到“/home/zgq/linux/Linux_Drivers/”目录输入“mkdirMyMutexLED回车”,创建“MyMutexLED”目录输入“ls回车”查看“/home/zgq/linux/Linux_Drivers/”目录下的文件和文件夹2、添加gpio_led节点......
  • 【10】Python3之使用openpyxl,操纵表格
    使用openpyxl,读取Excel文件fromopenpyxlimportload_workbook#加载工作簿,后面写Excel的路径wb=load_workbook(r"C:\Users\以权天下\Desktop\月光.xlsx")#选择活动工作表或特定工作表wb.activesheet=wb['2024']#2024是表名Excel_data=sheet['A2'].value#A2是单元格......
  • 【VC++学习笔记】控件及按钮的设置和使用
    1:按钮的使能与禁止用ClassWizard的MemberVariables为按钮定义变量,如:m_Button1;则m_Button1.EnableWindow(true);使按钮处于允许状态m_Button1.EnableWindow(false);使按钮被禁止,并变灰显示2:控件的隐藏与显示用CWnd类的函数BOOLShowWindow(intnCmdShow)可以隐藏或显示......
  • Virtualbox7安装及使用详细步骤
    前期准备Virtualbox软件安装包Downloads–OracleVMVirtualBoxcenterOS7镜像centos-7-isos-x86_64安装包下载_开源镜像站-阿里云(aliyun.com)安装Virtualbox使用管理员身份运行VirtualBox-7.0.14-161095-Win.exe进入向导界面,除了更改安装路径外,其他......
  • 使用useCallback包裹后,参数类型就变成了any
    在使用React的useCallbackHook时,如果直接包裹一个函数而没有提供类型参数,TypeScript会默认认为回调函数的参数类型为any。这是因为useCallbackHook接受两个参数,第一个是回调函数,第二个是一个依赖数组,而TypeScript在没有明确指定类型的情况下无法推断回调函数的参数类型。要解决......
  • Mimikatz使用教程
    介绍Mimikatz是一款开源的Windows安全工具,它被作者定义为“用来学习C语言和做一些Windows安全性实验的工具”。Mimikatz工具在Windows操作系统中运行时,可以从内存中提取出操作系统的明文密码、哈希、PIN码和Kerberos票据等,并支持哈希传递(pass-the-hash)、票据传递(pass-the-tick......
  • 数组基础使用
    关于数组①数组定义之后大小不能改变②数组内元素数据类型相通不允许出现不同类型③数组内的元素可以是任何数据类型包括基本数据类型和引用数据类型④数组变量属于引用类型,数组也可以看做是对象,数组的每个元素的相当于这个对象的成员变量⑤数组本身是对象Java中对象是在......