Vector 是C++中STL容器(container)中其中一个template class,他在宣告后就可以使用。只需要一直进行新增资料,而不用在乎其大小,亦可视为会自动扩展容量(capacity)的阵列,所以只要一直塞一直塞一直塞就可以了XD。是C++标准程式库中的众多容器(container)之一。
Iterator有时又称cursor,是一种在很多程式语言中都有的interface,主要功能就是让工程师可以无需关心memory分配而在各种container中进行寻访。 C++虽然本身不具此功能,但在STL中对于此进行了实作。会绑定所指向的容器。因此Iterator可以视为容器(在这就是用于vector)的指标的概念,因此亦可以直接做+n表示向后位移n个元素。
// 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()去增加记忆体:
少用operator[]去做存取:
因为operator[]不会进行边界检查,若程式过于庞大,出错时会很难找出错误,建议还是使用at(i)。
少用resize(),改用reserve():
先resize()后会先填0进去,用reserve()再push_back()元素进去会更好,且超过resize大小超过capacity时,记忆体会先双倍配置,若用不到那么多记忆体的话会过度浪费。