STL容器vector
2017-09-29 10:05
162 查看
Vector
定义于头文件<vector>
template< class T, class Allocator = std::allocator<T>> class vector;
Vector的能力
Vector支持随机访问,因此只要知道位置,就可以在常亮时间内访问任意元素。vector提供随机访问迭代器,所以适用于任意STL算法。capacity函数返回vector实际容纳量,如果超过这个量,vector必须重新分配内部内存。一旦内存重新分配,vector元素相关的所有reference、pointer和iterator都会失效,内存重新分配很耗时间。你可以使用reserve函数保存适当容量,避免重新分配:
std::vector<int> v; v.reserve(80);//reserve mempry for 80 elements
vector不能使用reserve缩减容量,调用reverse所给的实参如果小于当前vector的容量,不会引发任何效果。,既然vector的容量不会缩减,我们就可以知道,及时删除元素,其reference、pointer和iterator也会继续有效,继续指向动作发生前的位置。然而安插动作可能会使reference、pointer和iterator实效,因为会使vector重排。
C++11引入一个新的函数shrink_to_fit:这个函数不具有强制力的要求,可以缩减容量以符合当前的元素个数。
v.shrink_to_fit();//注意不具有强制性
在c++11之前有一个小技巧实现这个功能。
template<typename T> void shrinkCapacity(std::vector<T>& v) { std::vector<T> tmp(v); v.swap(tmp); }
你甚至可以像这样使用:
std::vector<T>(v).swap(v);
但是要注意的是,这些做法都会使reference、pointer和iterator换了只想对象。
Vector的操作
元素访问at 访问指定的元素,同时进行越界检查
operator[] 访问指定的元素
front 访问第一个元素
back 访问最后一个元素
data 返回指向内存中数组第一个元素的指针
当pop_back调用时,确保容器不为空是程序员的责任。例如:
std::vector<Elem>coll; if(!coll.empty()) { coll.pop_back(); }
关于效能,以下几种情况你可以预期安插动作和移除动作会快一些:
1. 在容器的尾部安插或移除元素
2. 容器的容量一开始就很大
3. 安插多个元素调用一次肯定是最快的
Vector并能没有提供任何函数可以直接移除“与某个值相等”的所有元素。但是可以通过以下做法。
std::vector<Elem> coll; coll.erase(remove(coll.begin(),coll.end(), val), coll.end());
如果只要一出第一个元素,可以这么做:
std::vector<Elem> coll; pos = find(coll.begin(),coll.end(), val); if(pos != coll.end()) { coll.erase(); }
将vector当做C-Style Array使用
reserve是容器预留空间,但并不真正创建元素对象,在创建对象之前,不能引用容器内的元素,因此当加入新的元素时,需要用push_back()/insert()函数。resize是改变容器的大小,并且创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。
std::vector<char> v; v.resize(41); strcpy(&v[0],"hello world"); printf("%s\n", &v[0]);
初次接触这两个接口也许会混淆,其实接口的命名就是对功能的绝佳描述,resize就是重新分配大小,reserve就是预留一定的空间。这两个接口即存在差别,也有共同点。下面就它们的细节进行分析。
为实现resize的语义,resize接口做了两个保证:
一是保证区间[0, new_size)范围内数据有效,如果下标index在此区间内,vector[indext]是合法的。
二是保证区间[0, new_size)范围以外数据无效,如果下标index在区间外,vector[indext]是非法的。
reserve只是保证vector的空间大小(capacity)最少达到它的参数所指定的大小n。在区间[0, n)范围内,如果下标是index,vector[index]这种访问有可能是合法的,也有可能是非法的,视具体情况而定。
resize和reserve接口的共同点是它们都保证了vector的空间大小(capacity)最少达到它的参数所指定的大小。
Class vector<bool>
vector<bool>特化版的内部只是用1bit存放元素,空间节省8倍。C++的最小可定址值是以byte为单位的,所以reference和iterator做特殊处理
vector<bool>无法满足其他vector的所有规定,例如
vector<bool>::reference并不是一个lvalue,
vector<bool>::iterator也不是一个随机访问迭代器,而且它的操作速度会比一般的vector慢因为他是bit操作。
flip函数用来取补数(complement)。注意,你可以对vector内的所有bit或单一bit调用filp,后者很值得注意,因为你也许会以为subscript操作符返回bool在对此基础类型调用filp是不可能的。然而
vector<bool>运用了一个名为proxy的技巧:面对一个
vector<bool>,subscript操作符的返回类型实际上是个辅助类,一旦你要求返回值为bool,便会触发一个自动类型转换函数。
所有用于元素访问的函数,返回的都是reference类型。所以可以这么写:
c.front().filp(); c[5] = c.back();
只有
vector<bool>的non-const容器才会用到内部的proxy类型reference。而用来处理那些const成员函数,返回类型都是const reference,那就是bool。
相关文章推荐
- 关于STL中vector容器的一些总结
- STL之vector容器详解
- STL基本容器: string、vector、list、deque、set、map
- STL顺序容器之vector类型
- STL顺序容器之向量(vector)
- C++标准库(STL)之vector容器的使用(包括特点、初始化、遍历与常用操作)
- STL 序列容器之vector
- stl中的容器、迭代器和算法----vector中的find实现
- stl提供了三个最基本的容器:vector,list,deque
- STL容器——vector接口介绍
- 带你深入理解STL之Vector容器
- C++STL容器技术之Vector
- [置顶] 从零开始学C++之STL(二):实现简单容器模板类Vec(vector capacity 增长问题、allocator 内存分配器)
- C++中防止STL中迭代器失效——map/set等关联容器——vector/list/deque等序列容器—如何防止迭代器失效—即erase()的使用
- C++STL中vector容器的用法
- C++ 有关STL中容器vector的操作 初始化 遍历 删除
- STL源码笔记(9)—序列式容器之vector(二)
- 在STL中基本容器有: string、vector、list、deque、set、map
- STL容器分析--vector
- stl容器区别(内存布局和使用场合): vector list deque set map