目录
前言:
1.vector模板
1.1vector简介
1.2创建vector类对象
2.array模板
2.1array简介
2.2创建array类对象
3.比较中学习
4.怎么避免数组越界访问
前言:
指针的基础用法分了近三篇文章,结合数组、结构、共用体、字符串一起学习。相信读者已经掌握了指针的基本知识,我们来补充一下在涉及指针第一篇内容里提到的,在C++中,用vector和array模板替代数组的使用。
1.vector模板
1.1vector简介
vector模板类是在C++98新增的标准模板库(STL)提供的,它是动态数组的替代品(new typename[element];)。既然和动态数组有关,所以用vector模板类创建数据对象的时候,最后要记得使用数组格式释放掉相应的自由存储空间(堆区)。接下来我们来讲如何创建vector对象。
1.2创建vector类对象
首先,使用vector模板要使用头文件vector,vector的名称空间在std里面,使用编译指令using就可以啦,需要声明的声明好后,就可以使用vetor创建对象。
vi,vt,这里并不是英语里的不及物和及物动词的意思,碰巧这么起而已(doge)。vi是一个vector<int>的对象。这句话可以这样理解,vector是类,用类创建的对象,是什么样的?vector<int>样的,就像char ch;用char创建一个ch对象一样,只是char是基本类型,我们更常说,ch是一个char类型的变量。
由于vector对象的大小可以根据我们的输入自动调整,所以可以在声明的时候,不指定数组的元素个数是可以的。而用静态联编创建数组int arr[元素个数];的时候,元素个数不能给0。
2.array模板
2.1array简介
array是在C++11中新增加的,如果想使用长度固定的数组,使用array是一个更好的选择。vector的效率相比于数组是稍低的。我们说C、C++在数组进行访问的时候,对索引值不敏感,也就是可能超出数组的范围越界访问了而不报错。为了寻求功能更强大,更安全的长度固定的数组,我们引进了array类。
2.2创建array类对象
一样的,需要引用头文件为<array>才能使用array模板,名称空间位于std。
因为array是在C++11新增的,此时C++将使用列表初始化成为通用的一种方法,而在C98下vector对象不能使用列表初始化。
3.比较中学习
我们使用数组创建了arr1,vector创建了arr2,array创建了arr3、arr4。
vector对象不能被初始化,通过数组表示法来赋值,我们可以把vector创建的对象arr2当成一个数组,用数组表示法来使用,array对象也一样可以用。
arr4 = arr3;当数组元素一样,个数相同时,array类的对象是可以相互赋值的。我们看到打印arr4[2] = 3.14内容,可以记得更深刻一些。
arr1的地址是0x008FF780,arr2的地址是0x00ACF758。这两个地址相差很大,这是因为,arr1数组是在栈区内存上的,vector是在堆区(动态数组替代品,动态开辟的空间在堆区)内存上的。我们只需要知道,栈区和堆区是内存中两块相对独立的内存块,地址相差很大就可以了。
补充:堆区也叫内存池。
而arr1与arr3、arr4相差不大,甚至可以看到arr3、arr4两者几近是靠在一起创建的,当然也不是连续的,只是比较起arr2很近。这是因为array创建的数组,也和arr1性质上也是相同的,固定长度的数组,局部,所以都是在栈区上开辟空间。
看到arr1[-1],相信大部分读者都反应过来说,数组arr1越界访问了。是的,我们看到右边窗口说代码退出是3,这是异常退出的意思,3是个错误代码信息的编号,代码退出0才是正常的。我们主要不是想讨论这个,而是说,结果是不是还是跑出来了?arr1[2]的地址是0x00FF780,arr[-1]是*(arr1-1)的意思,它们相差三个元素的位置,每个元素是double类型,算下来恰是地址0x8FF768。这里想告诉大家的是,C、C++没有检索下标使用有效性的这个保护机制,如果有编译器它都不让你跑起来,而这里是跑完再报错,但内容还是被改了。
4.怎么避免数组越界访问
第一:足够细心。第二:让代码健壮一点。
人难免会不经意的写出一个bug,所以为了保护好代码,适当加入写监督的机制。这里讲的是对C++中的vector类和array类使用at成员函数,来是程序在运行的时候,捕获非法索引的情况,程序默认中断。
使用的例子:array<int, 5> arr1; arr1.at(5);
读者可能会问,那和前面报错有什么区别,我一样找不出原因呀,请注意,C和C++没有捕获这种索引值越界的。在一个工程中,当我们越界访问的时候,没有报错,且没有终止(但一般都会),最后输出一个奇怪的结果,试问几万行里的代码,要怎么找bug。不过介于博主知识有限,可能这个at成员报错会有提示在第几行呀,或者是我们自己添加一些可以快速定位到位置等等。大家知道这么一回事就可以啦,在日后的学习中,懂得更多!
还有一点就是,使用at()的代价是需要额外的时间去让编译器检查,这也是C和C++允许我们使用任何一个索引值的原因所在。另外这些类还有成员函数,begin()、end()。让我们确定开头和结尾这个边界,以免超过这个范围。这里就不细说啦,认识认识。
好啦,到这就讲完了,希望读者读完有所收获。
如果本文有内容、排版上的错误,请在下边评论区留言哈。求点赞,求点赞,求点赞!你的点赞是我更新的动力~