STL之vector
容器是包含其他对象的对象,标准C++库中提供了一系列的容器,这些容器可以分为两种类型,顺序容器和关联容器。顺序容器可提供对自身元素的顺序访问或者随机访问,标准C++库提供了3种顺序容器,即vector、list、deque;关联容器则是用关键字对关键元素进行访问,标准C++库提供了4种关联容器,即map、set、multimap、multiset。
参见C++ Reference:http://www.cplusplus.com/reference/vector/vector/?kw=vector
template < class T, class Alloc = allocator<T> > class vector; // generic template(通用模板)Vectors are sequence containers representing arrays that can change in size.
[vector是一个顺序容器,是一个可以动态改变大小的动态数组。]
Just like arrays, vectors use contiguous storage locations for their elements, which means that their elements can also be accessed using offsets on regular pointers to its elements, and just as efficiently as in arrays. But unlike arrays, their size can change dynamically, with their storage being handled automatically by the container.[就像数组一样,vector中的元素是顺序存储的,这意味着你可以像操作数组那样使用offset来高效的访问vector中的元素。但不同于数组的是vector的大小可以动态的改变。]
Internally, vectors use a dynamically allocated array to store their elements. This array may need to be reallocated in order to grow in size when new elements are inserted, which implies allocating a new array and moving all elements to it. This is a relatively expensive task in terms of processing time, and thus, vectors do not reallocate each time an element is added to the container.[vector动态改变大小在内部的实现方式是通过一个动态分配的数组来存储元素,当新元素被插入时,这个数组可能会通过再分配的方式来增加大小,也就是说可能会分配一个新数组并把原有的元素都放到新数组里。再分配是一个相对比较费时的操作,因此在插入新元素时,vector不会每次都再分配。]
Instead, vector containers may allocate some extra storage to accommodate for possible growth, and thus the container may have an actual capacity greater than the storage strictly needed to contain its elements (i.e., its size). Libraries can implement different strategies for growth to balance between memory usage and reallocations, but in any case, reallocations should only happen at logarithmically growing intervals of size so that the insertion of individual elements at the end of the vector can be provided with amortized constant time complexity (see push_back).
Therefore, compared to arrays, vectors consume more memory in exchange for the ability to manage storage and grow dynamically in an efficient way.[vector容器可能会分配多余的存储空间来适应可能的增长,也正是这样,vector的容量可能会比实际存储的元素数量大。库可以通过不同的策略来达到增加vector大小时的内存使用和再分配之间的平衡,但无论何种实现,增加大小时的再分配的时间复杂度都应该是对数级的,这样可以保存在vector尾部插入一个元素所平摊的时间复杂度是一个常数。因此,相较于数组而言,vector需要耗费更多的内存来管理存储空间以及高效的动态增加大小。]
Compared to the other dynamic sequence containers (deques, lists and forward_lists), vectors are very efficient accessing its elements (just like arrays) and relatively efficient adding or removing elements from its end. For operations that involve inserting or removing elements at positions other than the end, they perform worse than the others, and have less consistent iterators and references than lists and forward_lists.
[与其他动态顺序容器(比如队列、列表、前向列表)相比,vector可以非常高效的访问元素(就像数组那样),并且可以相对高效的在尾部增减元素,但如果是在尾部之外的地方插入和删除元素,vector的表现就不如其他动态顺序容器。]
/* //构造函数 vector<int> first //创建一个空的向量容器 vector<int> first(4) //创建一个向量容器first,容器中有4个int型元素,初始值为0 vector<int> first(4,2) //创建一个向量容器first,容器中有4个int型元素,初始值为2 vector<int> first(const_iterator begin,const_iterator end) //创建一个向量容器first,容器中的元素为指定元素,范围从[begin,end) vector<int> first(vector &x) //创建一个向量容器first,容器元素为另一个容器x中的元素 */ #include <iostream> #include <vector> using namespace std; template<class T> void show(vector<T> &one) { cout<<"size()="<<one.size()<<"\t"<<"capacity="<<one.capacity()<<endl; for(int i=0;i<one.size();++i) cout<<one[i]<<" "; cout<<endl; } int main() { vector<int> one; show(one); vector<int> two(4); show(two); vector<int> three(4,3); show(three); vector<int> four(three.begin(),three.end()); show(four); vector<int> five(four); show(five); int myints[]={2,4,5,6}; vector<int> six(myints,myints+sizeof(myints)/sizeof(int)); show(six); system("pause"); return 0; }
/* //一些方法
size() //返回向量容器中当前实际有多少个元素
capacity() //返回向量容器中所能容纳的元素数量
empty() //检测容器是否为空,是,返回true
clear() //清空所有元素
swap(vector &x) //交换两个vector
front() //返回第一个元素的引用
back() //返回最后一个元素的引用
at(size_type n) //返回指定位置的元素的引用,若越界,则抛出out_of_range异常
operator[](size_type n) //返回指定位置的元素的引用,若越界,则导致未定义的行为(undefined behavior)
push_back(value_type& val) //向向量容器的尾部添加元素,若新vector的大小超过当前vector的容量,则再分配
pop_back() //移除最后一个元素
注:若再分配,与容器相关的所有迭代器、指针及引用都无效;否则只有尾部的迭代器无效
begin() //返回指向第一个元素的迭代器
end() //返回指向最后一个元素的下一位(past-the-end)的迭代器
rbegin() //返回指向最后一个元素的逆向迭代器
rend() //返回指向第一个元素的前一位(preceding the first element)的逆向迭代器
*/
#include <iostream> #include <vector> #include <string> using namespace std; template<class T> void show(vector<T> &one) { cout<<"size()="<<one.size()<<"\t"<<"capacity="<<one.capacity()<<endl; for(int i=0;i<one.size();++i) cout<<one[i]<<" "; cout<<endl; } int main() { vector<int> myvector(10); for(unsigned i=0; i<myvector.size(); i++) myvector.at(i) = i; show(myvector); system("pause"); return 0; }
/* //inserting into the vector iterator insert(iterator position, const value_type& val) void insert(iterator position, size_type n, const value_type& val) void insert(iterator position, const_iterator first, const_iterator last) Insert elements The vector is extended by inserting new elements before the element at the specified position, effectively increasing the container size by the number of elements inserted. [在position所指向的元素之前插入新元素] This causes an automatic reallocation of the allocated storage space if -and only if- the new vector size surpasses the current vector capacity. [如果新vector的大小超过当前vector的容量,则再分配] Because vectors use an array as their underlying storage, inserting elements in positions other than the vector end causes the container to relocate all the elements that were after position to their new positions. This is generally an inefficient operation compared to the one performed for the same operation by other kinds of sequence containers (such as list or forward_list). [因为vector内部是使用数组来存储元素,因此在尾部之外的地方插入元素会导致在position及position之后的元素被重新分配位置(即position及position之后的元素全部往后移,这个操作相较于其他顺序容器(比如列表和前向列表)而言通常是低效的)] Return value
An iterator that points to the first of the newly inserted elements.
[返回值是指向第一个新插入元素的迭代器(如果函数有返回值的话)]
Member type iterator is a random access iterator type that points to elements.
[iterator是一个指向元素的随机存储迭代器]
Iterator validity
If a reallocation happens, all iterators, pointers and references related to the container are invalidated.
Otherwise, only those pointing to position and beyond are invalidated, with all iterators, pointers and references to elements before position guaranteed to keep referring to the same elements they were referring to before the call.
[如果发生再分配,所有的迭代器、指针和引用都会失效;否则只有指向position及position之后位置的迭代器、指针和引用才会失效,其他位置则保持不变]
*/
#include <iostream>
#include <vector>
using namespace std;
template<class T>
void show(vector<T> &r)
{
cout<<"size="<<r.size()<<"\t"<<"capaticy="<<r.capacity()<<endl;
for(int i=0;i<r.size();++i)
cout<<r[i]<<" ";
cout<<endl;
}
int main()
{
vector<int> myvector(3, 100);
show(myvector);
vector<int>::iterator it = myvector.begin();
it=myvector.insert(it, 200); //增加一个元素后,myvector的capacity由3变为4,说明旧内存块被释放,因此迭代器it失效,需要重置
show(myvector); vector<int> another_vector(2, 400); myvector.insert(it+2, another_vector.begin(), another_vector.end()); show(myvector); int myarray[]={501,502,503}; myvector.insert(myvector.begin(),myarray,myarray+3); show(myvector); system("pause"); return 0; }
/* //erasing from vector iterator erase (iterator position); iterator erase (iterator first, iterator last); Erase elements Removes from the vector either a single element (position) or a range of elements ([first,last)). [从容器中删除一个元素(position处)或者一组元素(范围是[first, last])] This effectively reduces the container size by the number of elements removed, which are destroyed. [该操作会有效地缩小vector的长度] Because vectors use an array as their underlying storage, erasing elements in positions other than the vector end causes the container to relocate all the elements after the segment erased to their new positions. This is generally an inefficient operation compared to the one performed for the same operation by other kinds of sequence containers (such as list or forward_list). [因为vector内部使用数组存储元素,因此在尾部之外的地方删除元素会导致在被删除元素之后的所有元素被重新分配位置,这个操作相较于其他顺序容器,比如列表或者前向列表来说,通常是一个低效的操作] Return value An iterator pointing to the new location of the element that followed the last element erased by the function call. This is the container end if the operation erased the last element in the sequence. [返回值是最后一个被删除元素的的下一个元素的迭代器,如果删除操作发生在尾部,则返回的是end] Member type iterator is a random access iterator type that points to elements. [iterator是一个指向元素的随机存储迭代器] Iterator validity Iterators, pointers and references pointing to position (or first) and beyond are invalidated, with all iterators, pointers and references to elements before position (or first) are guaranteed to keep referring to the same elements they were referring to before the call. [指向position及position之后的迭代器、指针和引用都无效;其他都保持不变] */ #include <iostream> #include <vector> using namespace std; template<class T> void show(vector<T> &r) { cout<<"size="<<r.size()<<"\t"<<"capaticy="<<r.capacity()<<endl; for(int i=0;i<r.size();++i) cout<<r[i]<<" "; cout<<endl; } int main() { vector<int> myvector; for(int i=1;i<=10;i++) myvector.push_back(i); show(myvector); vector<int>::iterator it = myvector.begin(); it = myvector.erase(myvector.begin()); show(myvector); cout<<"*it = "<<*it<<endl; it = myvector.erase(myvector.begin()+1,myvector.begin()+4); show(myvector); cout<<"*it = "<<*it<<endl; system("pause"); return 0; }
/* // vector assign void assign(size_type n,const value_type& val) void assign(const_iterator first,const_iterator last) Assign vector content Assigns new contents to the vector, replacing its current contents, and modifying its size accordingly. [重新分配vector的元素并相应改变vector的长度] Any elements held in the container before the call are destroyed and replaced by newly constructed elements (no assignments of elements take place).This causes an automatic reallocation of the allocated storage space if -and only if- the new vector size surpasses the current vector capacity. [容器中原有元素均被销毁并替换为新元素;如果新vector的大小超过当前vector的容量,则再分配]
Iterator validity
All iterators, pointers and references related to this container are invalidated.
[所有的迭代器、指针和引用都无效]*/ #include <iostream> #include <vector> using namespace std; template<class T> void show(vector<T> &r) { cout<<"size="<<r.size()<<"\t"<<"capaticy="<<r.capacity()<<endl; for(int i=0;i<r.size();++i) cout<<r[i]<<" "; cout<<endl; } int main() { vector<int> first(4,5); show(first); first.assign(2,4); show(first); first.assign(7,100); show(first); vector<int> second(10); for(int i=0; i<10; i++) second.at(i) = i; first.assign(second.begin(),second.end()-1); show(first); system("pause"); return 0; }
/* //resizing vector void resize (size_type n); void resize (size_type n, const value_type& val); Change size Resizes the container so that it contains n elements. [改变容器的大小使之长度为n] If n is smaller than the current container size, the content is reduced to its first n elements, removing those beyond (and destroying them). [如果n小于当前容器长度,则只保留前n个元素,其余元素销毁] If n is greater than the current container size, the content is expanded by inserting at the end as many elements as needed to reach a size of n. If val is specified, the new elements are initialized as copies of val, otherwise, they are value-initialized. [如果n大于当前容器的长度,则用指定元素填充剩下的元素;若没有指定填充元素,则用默认值填充] If n is also greater than the current container capacity, an automatic reallocation of the allocated storage space takes place. [如果n大于当前容器的容量,则再分配] Notice that this function changes the actual content of the container by inserting or erasing elements from it. [该函数使用插入和删除元素来改变容器的大小] Iterator validity In case the container shrinks, all iterators, pointers and references to elements that have not been removed remain valid after the resize and refer to the same elements they were referring to before the call. [如果容器长度减小,则指向没有被移动的元素的迭代器、指针和引用保持不变] If the container expands, the end iterator is invalidated and, if it has to reallocate storage, all iterators, pointers and references related to this container are also invalidated. [如果容器长度增加,则指向尾部的迭代器失效;如果发生再分配,则所有迭代器、指针和引用均失效] */ #include <iostream> #include <vector> using namespace std; template<class T> void show(vector<T> &r) { cout<<"size="<<r.size()<<"\t"<<"capaticy="<<r.capacity()<<endl; for(int i=0;i<r.size();++i) cout<<r[i]<<" "; cout<<endl; } int main() { vector<int> myvector; for(int i=1;i<=10;i++) myvector.push_back(i); show(myvector); myvector.resize(5); show(myvector); myvector.resize(8,100); show(myvector); myvector.resize(12); show(myvector); system("pause"); return 0; }
/* //vector::reserve void reserve (size_type n); Request a change in capacity Requests that the vector capacity be at least enough to contain n elements. [请求,使得容器容量至少能够容纳n个元素] If n is greater than the current vector capacity, the function causes the container to reallocate its storage increasing its capacity to n (or greater). [如果n比当前容器容量大,则该函数会导致再分配,使得容器容量增加至n] In all other cases, the function call does not cause a reallocation and the vector capacity is not affected. [其余情况下,该函数不会产生任何影响,既不会导致再分配,也不会改变当前容器容量] This function has no effect on the vector size and cannot alter its elements. [该函数不会影响当前容器的大小及其元素] Iterator validity If a reallocation happens, all iterators, pointers and references related to the container are invalidated.Otherwise, they all keep referring to the same elements they were referring to before the call. [如果发生再分配,则所有迭代器、指针和引用都失效;其他情况下保持不变] */ #include <iostream> #include <vector> using namespace std; int main() { vector<int>::size_type sz; vector<int> foo; sz = foo.capacity(); cout<<"making foo grow:\n"; for(int i=0; i<20; i++) { foo.push_back(i); if(sz != foo.capacity()) { sz = foo.capacity(); cout<<"capacity changed: "<<sz<<"\n"; } } vector<int> bar; sz = bar.capacity(); bar.reserve(20); // this is the only difference with foo above cout<<"making bar grow:\n"; for(int i=0; i<20; i++) { bar.push_back(i); if(sz != bar.capacity()) { sz = bar.capacity(); cout<<"capacity changed: "<<sz<<"\n"; } } system("pause"); return 0; }