认识、使用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()。让我们确定开头和结尾这个边界,以免超过这个范围。这里就不细说啦,认识认识。


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


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

相关文章
|
9月前
|
算法 编译器 C++
模拟实现c++中的vector模版
模拟实现c++中的vector模版
|
12月前
|
存储 编译器 C语言
【c++丨STL】vector的使用
本文介绍了C++ STL中的`vector`容器,包括其基本概念、主要接口及其使用方法。`vector`是一种动态数组,能够根据需要自动调整大小,提供了丰富的操作接口,如增删查改等。文章详细解释了`vector`的构造函数、赋值运算符、容量接口、迭代器接口、元素访问接口以及一些常用的增删操作函数。最后,还展示了如何使用`vector`创建字符串数组,体现了`vector`在实际编程中的灵活性和实用性。
684 4
|
11月前
|
存储 对象存储 C++
C++ 中 std::array<int, array_size> 与 std::vector<int> 的深入对比
本文深入对比了 C++ 标准库中的 `std::array` 和 `std::vector`,从内存管理、性能、功能特性、使用场景等方面详细分析了两者的差异。`std::array` 适合固定大小的数据和高性能需求,而 `std::vector` 则提供了动态调整大小的灵活性,适用于数据量不确定或需要频繁操作的场景。选择合适的容器可以提高代码的效率和可靠性。
|
11月前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
263 0
|
存储 C++ 索引
【C++打怪之路Lv9】-- vector
【C++打怪之路Lv9】-- vector
226 1
|
编译器 C++
【C++】—— vector模拟实现
【C++】—— vector模拟实现
|
算法 C++ 容器
C++之打造my vector篇(下)
C++之打造my vector篇(下)
122 0
|
存储 编译器 C++
C++之打造my vector篇(上)
C++之打造my vector篇(上)
153 0
|
4月前
|
测试技术 PHP 开发者
PHP 数组查找:为什么 `isset()` 比 `in_array()` 快得多?
PHP 数组查找:为什么 `isset()` 比 `in_array()` 快得多?
|
8月前
|
人工智能 Java
Java 中数组Array和列表List的转换
本文介绍了数组与列表之间的相互转换方法,主要包括三部分:1)使用`Collections.addAll()`方法将数组转为列表,适用于引用类型,效率较高;2)通过`new ArrayList&lt;&gt;()`构造器结合`Arrays.asList()`实现类似功能;3)利用JDK8的`Stream`流式计算,支持基本数据类型数组的转换。此外,还详细讲解了列表转数组的方法,如借助`Stream`实现不同类型数组间的转换,并附带代码示例与执行结果,帮助读者深入理解两种数据结构的互转技巧。
582 1
Java 中数组Array和列表List的转换