C++随记(四)---动态数组vector

C++随记(四)---动态数组vector

        前面两篇博文简单讲了一下C++通过new分配动态内存的问题。这一节就该轮到vector登场了,说实话我看完C++ Premier Plus的前半部分时(好吧说实话我是去年这个月就看了前半部分,今年这个月准备看完后面几章…也是浪的飞起,为了坚持看完,所以我才写了这些博文),最让我觉得很有意思,妙到可以拍手鼓掌的两个点:①模板类vector;②引用, 这两个东西简直让我服气啊,心里面在想:我靠,还有这种操作?

废话讲太多了,进入正题吧。

1、模板类vector;

      vector 是一种动态数组,我们可以在运行阶段设置vector对象的长度!而常规数组是一开始就要把长度给定下来。而且vector还能在末尾附加新数据,还可以在中间插入新数据。基本上,它是使用new创建动态数组的替代品,而且它确实就是用new和delete来管理内存的,但是这种工作是自动完成的,所以你使用vector的时候完全就可以忘掉我前面两篇博文讲的东西,直接拿来vector用就ok了。      4个要点: ①使用vector对象时要包含头文件:#include<vector> ②vector包含在名称空间std中; ③使用时还是应该像数组那样指出它存储的数据类型; ④可以有很多方法来指定它的元素数。

        我第一次见到vector是在使用Opencv的时候,经常看见用vector来装东西,对,我理解的就是vector就像一个篮子一样往里面塞东西就行了,这是我的第一印象。 经典的定义语句:

vector<数据类型> 对象名称 (元素个数)

①范例语句:

#include<vector>//这句话千万不要漏掉啊
using namespace std;
int n;
cin>>n;
vector<int> cars(n)

        这就是一个典型的例子,这里我想说的,注意我的元素个数n是一个变量,是手动输入的。这就比起数组是一个伟大的进步啊!

        你可以试试如果我把最后一行改成 int cars[n];是什么效果,编译器会报错的,告诉你那里不能用变量,因为数组定义的时候要确定元素个数!我觉得这其实是数组一个很过分的要求,我怎么能次次都做到知道需要多少个元素?我定义少了,运行时根本不够用,我定义多了,那不是浪费内存吗?

        幸运的是,vector的出现改变了这一情况,我的n不但可以手动输入,而且这个n也可以是通过其他步骤计算出来的n,这就让我能够做到视情况而定嘛,多么nice!而且就算我是在定义的时候才导入了n,假设我的n此刻等于5,但是我后面完全可以增加,减少元素个数,可以让他长成10个元素,也可以让他缩成2个元素,是不是很方便。

②范例语句 事实上我在定义vector的时候完全可以空着元素个数那一个地方不写,

vector<int>  cars;//这是合法的

这下我连n都不用考虑了,更nice了。

vector的基本操作: 以vector<int>  cars; 为例

①向动态数组vector的末尾添加元素—push_back( ):

for( int a = 1; a++ ; a<=5){
 cars.push_bcak( a );
}

此操作就是在每次循环时,往数组cars的屁股后面装入一个元素a. ②动态数组的长度—size( ): 由于我并未定义cars的长度,如果我现在需要用到它的长度该怎么半呢?

cars.size( );

上面表达式的值就是数组的长度了,函数size( )返回的是容器中元素数目。 ③动态数组的头—begin( ): 可以简单的理解为begin( )函数返回了数组第一个元素的地址(更精确的说法是返回了指向容器第一个元素的迭代器,可以理解迭代器为一个广义的指针)

cars.begin( );//就是我第一个元素cars[0]的地址了,注意也是从0开始算的

④动态数组的屁股—end( ): end( )返回了指向容器尾部元素的迭代器,理解为最后一个元素的地址。

cars. end( );//就是我最后一个元素的地址,此例中就是cars[4]的地址。

⑤插入元素—insert( ): 既然是动态数组,那么除了我常用的从屁股后面按照顺序一个一个添加元素外,也可以在数组中间插入元素。

cars.insert( cars.begin( )+ i , b);在第i+1个元素前面插入b;

这里就用到了cars.begin( )作为第一个元素的地址。自然+i之后就是原来的第i+1个元素的位置插入新的元素。 ⑥删除元素—erase( ): 能插入就能删除:

cars.erase ( cars.begin( )+ i);//删除第i+1个元素

⑦清空—clear( ):

如果觉得一个一个删除太麻烦了,我想把原来这个容器中的东西倒掉,重新装东西,那么: 
cars.clear( );

基本的操作就是这些,平常应该够用了,这里要提到一个问题,既然是vector类是动态数组,那么我用平常普通数组的方式访问其元素是否可以呢?如 cars[2]是否合法? 回答是合法的,我们甚至可以直接对其值进行修改.如: cars[2] = 100; 依然合法,这样的方式似乎合乎我们平时对于数组的概念 不过我更推荐使用成员函数.at() cars.at(2) = 100;这种方式是比较安全的访问方式,这里不详细解释了。至于究竟想用哪个方式,取决于你的具体程序。

特别注意:如果要访问或者修改其中某个元素的值,一定要保证这个位置的元素已经被初始化了,也就是说原来这里有一个值。 我举个例子,比如我定义 vector<int> vec; 然后我想对其进行赋值,vec[2] = 100; 或者vec.at(2) = 100; 这样做程序会报错!!!会提示内存溢出!!vector subscript out of range!  因为一开始并没有说你容器vec究竟有多大,所以vec.at(2)这个位置并没有被分配内存!我们如果直接访问的话就自然有问题了,而push_back( )函数是一个一个的往后接龙,所以不会出现问题,所以要想直接对元素这么搞,必须要初始化vec。 如何初始化呢?多用resize( )函数;

vec.resize( 5);

也就是给vec分配5个单位的内存空间,这样你直接对元素进行操作就能找到地方了。

注意:vector的类型不局限于int、double、char等,它包含的元素可以是结构体,也可以是vector,这就是二维动态数组了。

2、二维动态数组

用过MATLAB的同学应该知道,MATLAB对与矩阵操作是非常便捷的,但是C++中并没有矩阵这种概念,于是我们可以自己用二维数组代替矩阵来进行一些简单的操作。普通数组也有二维数组的形式,但依然需要我定义数组的时候就确定好数组大小,使用起来不方便,而二维的vector容器就能很好的解决这个问题。 如

vector<vector<int> > S;

就是一个二维动态数组,第一层vector的元素是 vector<int>,第二层vector的元素是int

现在就可以把它当作矩阵了,比如S[2][3],是第3行第4列的元素,因为数组从0开始

如图,第一个[ 2 ]表示这是第3个(从0开始算)子vector,而[3]表示是第3个子vector中的第4个(从0开始计数)int 元素。 注意如前文中提到,如果要用S[2][3]=10;这样的语句,一定要先对二维数组进行初始化:

上图是我自己的一个程序中用到二维数组时初始化的过程,注意N的值在我初始化二维动态数组之前是已经通过其他算式获得了确定的值了

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏xiaoxi666的专栏

状态机编程思想(1):括号内外字符串统计

我们拿到这个问题时,第一感觉往往是顺序遍历字符串,并检测左右相邻字符是否满足边界条件,从而进行分支处理。但是这样做有以下棘手之处:

723
来自专栏卡少编程之旅

Javascript一些优雅实现

34011
来自专栏诸葛青云的专栏

学了指针没学动态内存一切都白搭!C语言基础教程之内存管理

本文将讲解 C 中的动态内存管理。C 语言为内存的分配和管理提供了几个函数。这些函数可以在<stdlib.h>头文件中找到。

680
来自专栏coder修行路

《深入理解计算机系统》阅读笔记--信息的表示和处理(上)

结果是负数!!!! 这个结果理论上是非常不应该的,这已经违背了我们的常识,毕竟正数的乘积,最后的结果应该还是一个正数,但是这里出现负数的情况,虽然结果不对,但是...

650
来自专栏coder修行路

《深入理解计算机系统》阅读笔记--信息的表示和处理(上)

1643
来自专栏Ldpe2G的个人博客

MXNet Scala 学习笔记 二 ---- 创建新的 Operator

962
来自专栏desperate633

LintCode 两个字符串是变位词题目分析代码

写出一个函数 anagram(s, t) 判断两个字符串是否可以通过改变字母的顺序变成一样的字符串。

692
来自专栏顶级程序员

谈谈 Python 的生成器

第一次看到Python代码中出现yield关键字时,一脸懵逼,完全理解不了这个。网上查下解释,函数中出现了yield关键字,则调用该函数时会返回一个生成器。那到...

3396
来自专栏前端黑板报

一个数字截取引发的精度问题(二)

上篇文章只是简单介绍了Number的 toFixed 方法,周末抽时间把 Number 里的一些方法又看了一下,其中有个方法引起我的注意: Number.pro...

1896
来自专栏ml

C/C++ 一段代码区分数组指针|指针数组|函数指针|函数指针数组

1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<windows.h> 4 /* 举列子说明什么是...

2695

扫码关注云+社区