1含义:
包装C++内建的数组,编译期指定数组的维数;例如array<int,5>等价于int a[5]
提供类似STL容器的接口:
本质:对静态数组的包装,原始数组作为它代理的对象-------可以理解为代理模式
2、使用条件:对性能要求很高,或不需要动态数组时
3、实现摘要---模板类
template<class T,size_t N>// 数组元素的类型和大小
class array
{
public:
T elems[N];
begin();开始迭代器,相当于首指针
end(): 结束迭代器,等价末指针+1
operator[]();
at(); 类似[],会检查范围
front();首元素的引用,elem[0]
back();末元素的引用,elem[N-1]
size();容器大小,N
max_size();容器大小,N
empty();是否为空,总是false
data();
c_array();以C数组的形式返回内部数组指针
swap(); array对象交换
assign(); 所有元素赋值为value
};
4、重点解析data();以C数组的形式返回内部数组指针
c_array();以C数组的形式返回内部数组指针array<int,10>ar;
ar.assign(0);//所有元素为0
赋值指针:
int *p=ar.c_array();
*(p+5)=2;//ar[5]
ar.at(8)=10;
与STL算法结合:
sort(ar.begin(),ar.end()):
与assign库搭配时,不能调用与insert,push_back/front同名的assign库函数
array<int,3>ar=(list_of(2)(4));//只能用list_of5.缺陷
1】没有构造函数,不能指定大小和初始值(只能用模板参数指定大小)
2】因为不能动态增长,没有push_back()/front(),
也不能搭配插入迭代器适配器
3】应用场合:已知数组大小,
或对运行速度要求很高
---------------------------------------------------------------------------------------------------------------
1)多维容器,可动态增长,方便管理内存;
C++的多维数组和vector<vector<T>>的缺点是不方便使用;
2)multi_array 是递归定义的,每个维度都是一个multi_array,最底层是一个一维的multi_array,
因此multi_array是组合模式的一个具体应用。
2)使用
索引范围不一定从0开始:例如
typedef multi_array<int,3>ma_type;
typedef ma_type::extent_range range;
ma_typema(extents[range(1,5)][4][range(-2,2)]);
第一维索引:1-4
第二维 0-3
第三维 -2-1
ma[1][0][-2]=1;第一个元素如普通二维数组一样使用:
for (i=0;i<2)
for (j=0;j<2)
(*mp)[i][j]=v++;
声明方式:
multi_array<int,3>ma(extents[2][3][4]);
--------------------------------------------------------------------------------------------------------------
C++二进制的处理工具的缺点:
1】vector<bool>:内部不真正存储bool值,而是以bit来压缩保存,不是容器,不满足容器的定义。可动态增长,但不方便进行位运算。
2】bitset:大小固定,不可动态增长,支持位运算。
boost.dynamic_bitset的优点:方便位运算+动态增长
与bitset的接口几乎相同;
唯一的区别:大小在构造函数中由参数指定(类似array和ref_array的关系),而且运行时是动态可变的。
部分实现摘录:
class dynamic_bitset
{
swap()
resize();运行时调整容器的大小,变小时,多余的抛弃
clear();
push_back();
append();
operator&= [] ~
operator!=
set();全部置1或0
reset();全部或特定位为0
flip();反转全部或特定位
test();第N位是否为1
any();容器存在二进制位1,返回true
none()没有二进制位1
count();二进制位1的数量 db.count()
}使用:
dynamic_bitset<>db1(string("101011"));产生临时变量
dynamic_bitset<>db2(db1);拷贝构造
dynamic_bitset<>db2=db1;赋值
db.resize(10,true);db.size()当前容纳的二进制位的个数
db.clear();清空2个容器做位运算:例如db1^db2
集合操作:
db1=10101
db2=10010
b1|db2 并集 10111
b1&db2 交集 10000
b1-db2 差集 00101
筛选法求质数:处理前设置所有位为1:
db.set();
注:find_next(pos);从第pos位开始,返回第一个值为1的位置,否则返回npos
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
散列容器[
本质:无序的]
避免与非标准hash_xxx冲突
标准:选用unordered_xxx:
1.内部:散列表
1)
桶存储元素+散列值相同的元素放入同一个桶中
2)插入元素时自动增加桶的数量
例子:
unordered_set<int>us(100);使用100个桶
us.rehash(200);200个桶
2、查找复杂度:常数
比较谓词参数:equal_to<>,不是less<>,因为无序
3.要使自定义类型放入
unordered中,自定义类型需要满足如下条件:
1),提供散列函数;即编写hash_value函数,创建函数对象;
2),提供相等比较谓词,默认equal_to即使用operator==。
例子:struct demo_class
{
int a;
friend bool operator==(const demo_class&l,const demo_class &r)
{return l.a==r.a;}
};
size_t hash_value(demo_class&s)
{return boost::hash<int>()(s.a);}
void main()
{
unordered_set<demo_class>u;
}
----------------------------------------------------------------------------------------------------------------------
STL中的
map和multimap:只能提供key--->value的映射,不能提供值到键的映射;
即只有单向映射能力。
boost.bimap:双向映射能力,左右视图left,right相当于不同方向的std::map。
例如:
bimap<x,y>
bimap.left相当于map<x,y> 左视图-----提供值到键的映射
bimap.right相当于map<y,x>右视图---提供键到值得映射
2、实现摘要
class bimap
{
left_map left;//左右视图
right_map right;
by();
project();
project_left();
project_right();
project_up();
};
使用:
bimap<int,string>bm;
初始化后
bm.left.find(1);//通过左视图查找
bm.right.find("1");//通过右视图查找
插入:
bm.left.insert(bmt::left_value_type(1,"one"));
bm.right.insert(bmt::right_value_type("ttt",2));1,key/value对必须都唯一;,
2,两个视图的迭代器返回值都是常量对象,相当于pair<const,const>,
不能向std::map那样修改value的值
3,不能使用operator[]和at(),不能像关联数组那样使用。
1,key/value对必须都唯一;,
2,两个视图的迭代器返回值都是常量对象,相当于pair<const,const>,
不能向std::map那样修改value的值
3,不能使用operator[]和at(),不能像关联数组那样使用。
---------------------------------------------------------------------------------------------------------------------
pair是tuple的特例,即2-tuple仅有两个元素。
2)默认支持10个模板类型参数,即10-tuple;
3)如果类型不支持缺省构造或赋值,tuple功能会相应缺失。
4)tuple代价和struct几乎相同,可代替struct
5)
优点:使用方便,有许多可用操作元素的方法;
缺点:使用模板技术,会带来大量的模板实例化推演,导致编译时间增加;
场合:大型程序中,编译只是很少的一部分,可用tuple
2、使用
typedeftuple<int,string,double>tuple3;
tuple4=tuple3;赋值
如果tuple元素类型为&,初始化时必须赋值:
int x=10;
tuple<int&>t(x);
ref包装引用:
tuple<int,string&>tuple1=make_tuple(i,ref(s));//必须用ref产生引用
tuple<cosntint&,string&>tuple1=make_tuple(cref(i),ref(s));//必须用ref产生引用get<>():访问内部的值
t.get<0>()==1
t.get<2>()==100注意:不能使用for循环访问
因为get<>()是一个模板函数,编译进行模板实例化时要求模板参数<int N>
必须是编译期可确定的。而for中的i运行时确定。
例如:下面的是错误的
for (i=0;i<3;++i)
cout<<t.get<i>();可以使用递归访问:
template<typename TUPLE>//模板函数
void prin(const TUPLE&t)
{
cout<<t.get_head();
prin(t.get_tail())
}
为递归终止,定义null_type函数重载
void prin(const tuples::null_type&){}
3.作为函数返回值
typedeftuple<int,double,string>me;
mefun()
{returnmake_tuple(1,2.2,"sddd");}
main()
{
int i;
double d;
string s;
tie(i,d,s)=fun();
}
4、tie()
把变量连接到tuple上,生成一个元素类型全是&的tuple;
相当于make_tuple(ref(a),ref(b),...)
例如:
tie(i,d):生成临时变量,类型:tuple<int&,double&>
-----------------------------------------------------------------------------------------------------------
1、特点
1)对union的扩展,可以容纳复杂类型;
union:只能有POD普通数据类型,不能有string,vector等复杂类型。
2)与any不同:允许保存的类型必须在模板参数类别声明
例如:
variant<int,float,string>v;
v=1;
---------------------------------------------------------------------------------------------------------
其他对C++的改进
compressed_pair:与std::pair类似,应用空基类优化技巧。当两个成员之一是空类,则编译器就会“紧缩”compressed_pair的大小以节俭空间
———————————————————————————————————————————————————————————
总结:
STL容器 /C++ Boost对其增强的容器
C++内建数组 array
C++多维数组 multi_array
bitset dynamic_bitset
hash_xxx Unordered_xxx
map/multimap bimap
pair/struct tuple
pair compressed_pair
union variant