C语言-Vector与Iterator是什么?

Vector 是C++中STL容器(container)中其中一个template class,他在宣告后就可以使用。只需要一直进行新增资料,而不用在乎其大小,亦可视为会自动扩展容量(capacity)的阵列,所以只要一直塞一直塞一直塞就可以了XD。是C++标准程式库中的众多容器(container)之一。

Iterator有时又称cursor,是一种在很多程式语言中都有的interface,主要功能就是让工程师可以无需关心memory分配而在各种container中进行寻访。 C++虽然本身不具此功能,但在STL中对于此进行了实作。会绑定所指向的容器。因此Iterator可以视为容器(在这就是用于vector)的指标的概念,因此亦可以直接做+n表示向后位移n个元素。
 

在开始使用vector之前,有几个很重要的名词要先解释介绍,分别是:
size 表示目前该vector所拥有的元素个数
capacity:表示vector目前可容纳的最大元素个数。这个方法与记忆体的配置有关,它通常只会增加,不会因为元素被删减而随之减少。
大概就是长下面这:(是不是觉得很像别的blog的图呢)
(1) 宣告与一些基本:

// T可以放任何资料型态甚至是使用者自定类别(user-defined class)。 // 下面为三种较常用的宣告方式
vector < T > vec ; 
vector < T > vec ( n ); // 初始size= n 的vector,并且填满0或\0 
vector < T > vec ( arr , arr + n ); // 可以将一T*类别阵列赋予给vector 
vector < T > vec ( count , val ); // 将vec做初始化,将size = count,且塞满元素val。 // 要使用iterator前必须要在前面加上要指定的scope resolution operator(::) 
vector < 
            

T >:: iterator iter ; 
iter = vec . begin (); // 将vector的第零个元素位址绑定给iterator,之后就可以直接存取值了! 
vec . size (); // 回传拥有的元素个数。
vec . capacity (); // 回传最大可拥有的元素个数,此值只会越来越大不会变小。
vec . empty (); // 若为空,回传true。
vec . begin (); // 回传的vector的第零个元素的iterator。
vec . end (); // 回传的vector的第最后一个元素的iterator。

元素的存取:

vec [ i ];          \\如同一般array样,存取index为i的元素。少用。
vec . at ( i );       \\ vector本身的方法,存取时会做边界检查(检查size ),如果超过边界会抛出一个例外,这是和[]的差别。
vec . front ();     \\回传vector第一个元素值(同vec . at ( 0 ))。
vec . back ();      \\回传vector最尾端元素值(同vec . at ( vec . size ()- 1 ) )。 *( iter + i );       \\利用iterator进行第i个元素存取,就如同pointer一样加个*即可使用。

注意!千万不要用vec[i]与vec.at(i)进行元素新增,因为双方都不会改变size值,只能对已存在的元素进行修改!!!! (前者不会报错,后者会报错),要进行元素新增请用下面的方法。
 

元素的增删:
vec . push_back ( n );                \\核心函式。将元素n塞至vector的尾端并size + 1 。若size超过capacity时会再进行记忆体配置。
vec . pop_back ();                  \\删除vector最尾端的元素,size会- 1 。很像stack的pop 。
vec . insert ( iterator pos , n );     \\将元素n插入至vector内pos的位置之后。// 以下的动作都会调整size大小,毕竟size代表的就是元素个数
vec . erase ( iterator pos );         \\删除vector中位置pos的元素。
vec . erase ( iterator first , iterator last ); \\删除vector中位置first ~ last - 1的元素。
vec . clear ();                     \\清空所有元素。

容器的大小管理:

vec . reserve ( n );         \\改变vector整体的最大容量( capacity )为n ,且n必须大于capacity ,也就是只能变大,否则不会做事。类似realloc 。
vec . resize ( n );          \\改变vector的拥有元素数( size )成n 。size变少时多的元素会被移除;变多时则是补0 (或\0 )。类似calloc 。

注意以上两种改变的是不同的东西。且若resize的大小大于原本的capacity,vector也会跟着重新分配记忆体唷。
另外,虽然push_back()真的很好用,但毕竟一直使用会造成过多的记忆体重新配置, 因此可以的话还是最好都是先使用reserve()进行空间配置再push_back(),超过前再重新reserve(),可以减少过多的重新配置与记忆体浪费。

容器的通用函式:

vec . swap ( tmp );          \\ tmp和vec为相同类别的vector 。此方法可以将两个长度不同的vector做内容交换。

pointer比较的例子吧

int n = 5 ; // (0) 宣告与给值// 使用vector与iterator 
vector <int> vec ; 
vec . reserve ( n ); 
vector <int> :: iterator iter = vec . begin (); //使用new与pointer int * ptr = new int [ n ]; // 先都塞值给两边,这边请勿对vec直接使用[]或at存值for ( int i = 0 ; i < n ; i + +) { 
   vec . push_back ( i * i ); 
   ptr [ i ] = i * i ; } // (1) 印出资料(不讨论使用[]operator) // Iterator: 两种方法分别是: // (a) 使用iterator做回圈,宣告时长得比较丑,
cout << " Iterator:" << endl ; for ( vector <int> :: iterator i = iter ; i < vec . end (); i + +) 
   cout << * i << " " ; 
cout << endl ; // (b) 使用索引做回圈,这方法和pointer相似for ( int i = 0 ; i < vec . size (); i + +) 
   cout << *( iter + i ) << " " ; 
cout << endl ; // Pointer: 
cout << " Pointer:" << endl ; for ( int i = 0 ; i < n ; i ++ )  
   cout << *( ptr + i ) << " " ; 
cout << endl ; // (2) 对容器/动态阵列重新分配大小// Iterator: 
vec .储备(vec    






。大小() + n ); 
cout << "vec 容量 = " << vec .容量() << endl ; // vec容量 = 10 // 指针:乱七八糟,而且动态数组的大小不能直接取得=~= int * tmp = new int [ n + n ]; for ( int i = 0 ; i < n ; i ++) 
 tmp [ i ] = ptr [ i ];删除指针;
ptr = tmp ;      

那么...怎么释放记忆体呢?(free memory of vector)

当我们对一个vector使用clear()之后,他会清空所有该vector中的元素;同时若元素为物件时也会逐一执行deconstructor(),并且让size()归零,然而该记忆体还是存在的,并不会因此被回收掉。使用dynamic array时可以使用delete进行记忆体删除,那么vector有delete吗?很遗憾的是没有,同时也没有专用的函式会进行记忆体释出,因此必须透过宣告一个空vector,将其与要删除的vector进行swap交换,就能做记忆体删除搂!
 

向量。清除();
向量()。交换(东西);

另外reserve()虽然可以释放memory,但仅限于增加capacity时对原先的vector释放,因此即使使用vec.reserve(0),仍然不等于释放memory唷。
 

那二维vector?

// 一般二维array int arr [ 3 ][ 2 ] = { 1 , 2 , 3 , 4 , 5 , 6 }; // 动态二维vector -> 给予vec初始值为3个"长度为2的int vector(并给初值为0)" 
vector < vector <int> > vec ( 3 , vector <int> ( 2 )); // do whatever you want like array; for ( int i = 0 ; i < 3 ; i ++) for ( int j = 0 ; j < 2 ; j ++) ( vec . at ( i )). at ( j ) = arr [ i ][ j ]; // vec.at(i). at(j)同vec[i][j]

注意!!!!因为">>"是关键operator,因此宣告时两个">"之间,一定要有空格!

另外vec在第二维宣告时,因为使用constructor,初始都塞满了0,因此等于整个vec是预先分配好记忆体空间的,所以才可以直接用at()进行资料存取而不用push_back()。

若好想使用push_back,可以参考以下:

// 一般二维array int arr [ 3 ][ 2 ] = { 1 , 2 , 3 , 4 , 5 , 6 }; // 干净的二维vector 
vector < vector <int> > vec ; for ( int i = 0 ; i < 3 ; i ++) { 
    vector <int>
       
 

排; for ( int j = 0 ; j < 2 ; j ++)
        行。Push_back ( arr [ i ][ j ]);
    向量。推回(行);}

使用时的其他建议与注意事项:

少依赖直接使用push.back()去增加记忆体:
push_back()确实是vector的卖点,但建议还是不要依赖他自动配置记忆体的功能,因为push_back()在发现capacity不够时,会将该vector记忆体做双倍大小重新配置,因此若重新分配太多次后,会导致记忆体过度浪费与过多不必要的记忆体重新配置,因此若能知道要用多少的记忆体,或最多会用多少时,还是建议直接先使用reserve(n)进行记忆体配置。

少用operator[]去做存取:

因为operator[]不会进行边界检查,若程式过于庞大,出错时会很难找出错误,建议还是使用at(i)。

少用resize(),改用reserve():

先resize()后会先填0进去,用reserve()再push_back()元素进去会更好,且超过resize大小超过capacity时,记忆体会先双倍配置,若用不到那么多记忆体的话会过度浪费。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值