认识、使用C++vector和array

简介: 认识、使用C++vector和array

前言:


 指针的基础用法分了近三篇文章,结合数组、结构、共用体、字符串一起学习。相信读者已经掌握了指针的基本知识,我们来补充一下在涉及指针第一篇内容里提到的,在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()。让我们确定开头和结尾这个边界,以免超过这个范围。这里就不细说啦,认识认识。


 好啦,到这就讲完了,希望读者读完有所收获。


 如果本文有内容、排版上的错误,请在下边评论区留言哈。求点赞,求点赞,求点赞!你的点赞是我更新的动力~

相关文章
|
2月前
|
存储 编译器 C语言
【c++丨STL】vector的使用
本文介绍了C++ STL中的`vector`容器,包括其基本概念、主要接口及其使用方法。`vector`是一种动态数组,能够根据需要自动调整大小,提供了丰富的操作接口,如增删查改等。文章详细解释了`vector`的构造函数、赋值运算符、容量接口、迭代器接口、元素访问接口以及一些常用的增删操作函数。最后,还展示了如何使用`vector`创建字符串数组,体现了`vector`在实际编程中的灵活性和实用性。
82 4
|
27天前
|
存储 对象存储 C++
C++ 中 std::array<int, array_size> 与 std::vector<int> 的深入对比
本文深入对比了 C++ 标准库中的 `std::array` 和 `std::vector`,从内存管理、性能、功能特性、使用场景等方面详细分析了两者的差异。`std::array` 适合固定大小的数据和高性能需求,而 `std::vector` 则提供了动态调整大小的灵活性,适用于数据量不确定或需要频繁操作的场景。选择合适的容器可以提高代码的效率和可靠性。
56 0
|
1月前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
39 0
|
3月前
|
存储 C++ 索引
【C++打怪之路Lv9】-- vector
【C++打怪之路Lv9】-- vector
29 1
|
3月前
|
编译器 C++
【C++】—— vector模拟实现
【C++】—— vector模拟实现
|
3月前
|
算法 C++ 容器
C++之打造my vector篇(下)
C++之打造my vector篇(下)
40 0
|
3月前
|
存储 编译器 C++
C++之打造my vector篇(上)
C++之打造my vector篇(上)
39 0
|
3月前
|
算法 C++ 容器
【C++】—— vector使用
【C++】—— vector使用
|
1月前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
110 67
|
3月前
|
人工智能 前端开发 JavaScript
拿下奇怪的前端报错(一):报错信息是一个看不懂的数字数组Buffer(475) [Uint8Array],让AI大模型帮忙解析
本文介绍了前端开发中遇到的奇怪报错问题,特别是当错误信息不明确时的处理方法。作者分享了自己通过还原代码、试错等方式解决问题的经验,并以一个Vue3+TypeScript项目的构建失败为例,详细解析了如何从错误信息中定位问题,最终通过解读错误信息中的ASCII码找到了具体的错误文件。文章强调了基础知识的重要性,并鼓励读者遇到类似问题时不要慌张,耐心分析。