vector是c++标准模板库中的一个容器,简单来说,vector是一个能够存放多种类型的动态数组,前提是每个vector只能装一个类型,说到这里提一下python的列表和元组,个人认为python的列表要比C++和java的容器好用的多,比如java,从1.5开始支持泛型编程,更安全了,但是编译的时候还是不带泛型。python中的列表和元组是没有类型限制的,比如,我在列表中存了一个×××数(python2.5),然后我再存一个字符型也没有问题,python对列表中的数据类型没有限制。为什么python能这么玩,下篇博客会专门介绍,python的内置数据类型和用法以及python的一些有趣的bug。
1.vector的数据结构:vector是在内存中开辟连续的存储区,其基本数据结构是顺序表,这种数据结构的优点:查询快,快速定位某个元素的位置,不用挨个遍历,但是插入慢,因为我在某个位置插入一个元素要移动后面的所有元素的位置,这让我想到N多老生常谈的面试题,比如像java中的ArrayList何LinkedList的区别。其实其本质都是考数据结构的顺序表和线性表。
2.vector的属性:vector之所以称之为动态数组,要从动态和数组2个角度考虑,所谓动态,就是可以动态扩展,比如vector中有size()方法,返回vector中数据的个数还有capacity()方法,返回此vector的容量,这两个方法的区别是:就像一个杯子,当前装了多少水用size(),能装多少水用capacity()方法:上段代码,看看vector是怎么动态追加的:
- //============================================================================
- // Name : test.cpp
- // Author : zhangpeng
- // Version :
- // Copyright : Your copyright notice
- // Description : vector in C++, Ansi-style
- //============================================================================
- #include
- #include
- using namespace std;
- extern "C"
- typedef vector<int> vec;
- int main() {
- vec va;
- va.reserve(20);
- printf("va capacity %d \n",va.capacity());
- printf("va size %d \n",va.size());
- for(int i = 0; i < 30; i++){
- va.push_back(i);
- }
- printf("va capacity %d \n",va.capacity());
- printf("va size %d \n",va.size());
- return 0;
- }
输出结果是:
va capacity 20
va size 0
va capacity 40
va size 30
这段代码的意思是:我先设定vector的容量为20(在用reserve()申请缓存区,这个缓存区是根据vector内部的动态数组确定大小的),size为0,然后我在va中追加30个元素,然后可以看到,capacity是动态增长的,当vector中的缓存不够用的时候,它就会动态的把自己的容量扩大1.5到2倍(有些书上说扩大2倍,其实不确切,或者作者没写过代码),当扩大缓存区的时候,先创建空的缓存区,然后把值拷贝到新的缓存区中,这样的操作让我想到了hibernate的merge()方法,这样的操作有弊端,比如我操作大对象,这样的话效率不高,操作基本数据类型要好些,那我们遇见复杂对象数据类型怎么办呢?我们可以操作该对象的指针,就是vector中存指针,这样效率会明显提升。
vector中的四个相关成员函数:size() 和capacity()刚才已经介绍过了,现在介绍一下reserve和resize() ,
reserve(n):强制vector把它的容量改为至少n个,如果当前容量大于n,泽vector忽略此操作,如果当前容量小于等于n则vector被强迫重新分配一次,因为他的容量要增加.
resize(n):如果当前大小超出,则销毁超出部分,如果当前大小小于n,则增加默认值。
3.vector成员函数的其他操作:
c.assign(beg,end) c.assign(n,elem)
将(beg; end)区间中的数据赋值给c。将n个elem的拷贝赋值给c。
c.at(idx) // 建议用这种操作,不要去下标。
传回索引idx所指的数据,如果idx越界,抛出out_of_range。
c.back()
传回最后一个数据,不检查这个数据是否存在。
c.begin()
传回迭代器中的第一个数据地址。
c.clear()
移除容器中所有数据。
c.empty()
判断容器是否为空。
c.end() //指向迭代器中末端元素的下一个,指向一个不存在元素。
c.erase(pos) // 删除pos位置的数据,传回下一个数据的位置。
c.erase(beg,end)
删除[beg,end)区间的数据,传回下一个数据的位置。
c.front()
传回第一个数据。
get_allocator
使用构造函数返回一个拷贝。
c.insert(pos,elem) //在pos位置插入一个elem拷贝,传回新数据位置
c.insert(pos,n,elem) //在pos位置插入n个elem数据,无返回值
c.insert(pos,beg,end) //在pos位置插入在[beg,end)区间的数据。无返回值
c.max_size()
c.~vector
4.vector的迭代器:
vector必须支持迭代功能,说到迭代功能,不得不说下STL种的迭代器。
迭代器中STL中扮演着很重要的角色. STL的核心思想就是:将数据结构和算法分离。而迭代器就是作为数据结构和算法的粘合层而存在的。在STL中,每一个容器而有一个自己的迭代器, 而vector的迭代器就是一个普通的指针。所以在vector中实现迭代功能就非常的简单了。代码如下:
- vec::iterator iter = va.begin();
- int i = 0;
- while(iter != va.end()){
- printf("va[%d] = %d \n ",i,*iter);
- iter ++;
- i++;
- }
5.回收vector的过剩内存:
这样做的目的是把vector的容量减少到需要的容量:
vector
解释一下:我们先建立一个va的拷贝,vector
今天就到这,问个问题,我要拿到vector的首地址除了用迭代器还能用其他办法吗?