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

作者:teeyohuang

邮箱:teeyohuang@163.com

本文系原创,供交流学习使用,转载请注明出处,谢谢

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的值在我初始化二维动态数组之前是已经通过其他算式获得了确定的值了

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值