对C++的改进之容器篇:array/multi_array/dynamic_bitset/Unordered/bimap/tuple/variant

array

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_of

5.缺陷

1】没有构造函数,不能指定大小和初始值(只能用模板参数指定大小)

2】因为不能动态增长,没有push_back()/front(),

也不能搭配插入迭代器适配器

3】应用场合:已知数组大小,

 或对运行速度要求很高

---------------------------------------------------------------------------------------------------------------

multi_array  组合模式的应用

1、特点

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]);

--------------------------------------------------------------------------------------------------------------

dynamic_bitset

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();

      对C++的改进之容器篇:array/multi_array/dynamic_bitset/Unordered/bimap/tuple/variant_第1张图片

       对C++的改进之容器篇:array/multi_array/dynamic_bitset/Unordered/bimap/tuple/variant_第2张图片

注:find_next(pos);从第pos位开始,返回第一个值为1的位置,否则返回npos

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Unordered

散列容器[

本质:无序的]

避免与非标准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;
}

----------------------------------------------------------------------------------------------------------------------

bimap

1、与map区别

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));

与map的区别:

1,key/value对必须都唯一;,

2,两个视图的迭代器返回值都是常量对象,相当于pair<const,const>,

不能向std::map那样修改value的值

3,不能使用operator[]和at(),不能像关联数组那样使用。


3、

与map的区别:

1,key/value对必须都唯一;,

2,两个视图的迭代器返回值都是常量对象,相当于pair<const,const>,

不能向std::map那样修改value的值

3,不能使用operator[]和at(),不能像关联数组那样使用。

---------------------------------------------------------------------------------------------------------------------

tuple

1、特点:
1)pair的泛化,可以从函数返回任意数量的值.即

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&>

-----------------------------------------------------------------------------------------------------------

Variant

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






















你可能感兴趣的:(对C++的改进之容器篇:array/multi_array/dynamic_bitset/Unordered/bimap/tuple/variant)