C++笔记十(STL与泛型编程)

本周内容
(1)一个万能的hash function
(2)Tuple用例
(3)Type traits以及traits 实现
(4)cout
(5)moveable元素对于容器速度效能的影响

一 一个万用的hash function

  • 但使用以hash table为底层的容器时,遇到一个难题,必须要为放的元素写一个hash function。正如东西是由原子分子组成一样,在计算机编程里面,所有的data也是由原始的整数、浮点数、字符串组成的,基本的数值型这些本身都有hash function,他们的hash function传回来的就是自己。有没有可能把一个设计出来的数据结构,一个元素,把它拆分开来,然后把它各自的hash code(hash function产生hash code)加起来,就变成这个元素的hash code,可以不可以这样做呢,好像言之成理。所谓的hash function是将将产生的hash code做到越乱越好,不要重复。
  • 下一段代码是hash function的写法形式:
#include<functional>
class Customer {
...
};
//-------------------------形式1成员函数---------------------
class CustomerHash
{
public:
    std::size_t operator()(const Customer& c) const {
    return...
};
//-----------------------------------------------------------
unordered_set<Customer,CustomerHash> custset;
//形式1模板参数只需要填元素类型和函数类型就可以,自动产生函数对象被调用
//-------------------------形式2一般函数---------------------
size_t customer_hash_func(const Customer& c){
    return...
};
//-----------------------------------------------------------
unordered_set<Customer,size_t(*)(const Customer&)>
custset(20,customer_hash_func);
//形式2模板参数需要填元素类型和函数类型,创建容器时候还要把真正的函数地址放进来
  • 将每个hash code相加太过天真:元素容易碰撞,每个篮子挂的元素多,查找慢。从TR1开始有了下面1234帮你写hash function。typename...表示可以接受任意多的模板参数。
  • 借由variadie templates这种语法,可以放任意元素个数,任意类型的参数。
  • 9e3779b9是黄金比例的应用。


    一个万用的hash function.png
  • 还有第三种形式实现,那就是通过对自己的元素作一个偏特化版本实现hash function。G4.9以后有了string的偏特化版本。


    偏特化实现hash function.png

二 tuple用例

  • C++11中的tuple(元组)是一个固定大小的不同类型值的集合,是泛化的std::pair。我们可以把他当做一个通用的结构体来用,不需要创建结构体又获取结构体的特征,在某些情况下可以取代结构体使程序更简洁,直观。tuple可以指定任意类型元素。
  • 通过继承自己(尾部的部分)实现递归。
    GNC4.8 tuple实作如下:


    tuple实作.png

    tuple用例如下:


    tuple用例.png

三 Type traits以及traits 实现

  • G2.9的type traits写的非常简单,泛化版本(默认)六个typedef,拷贝构造、析构函数等都是重要的,意味着如果要拷贝一百万个数据,要调用一百万个拷贝构造函数、析构函数。如果你写出一个类型,知道那个类型不重要,那就可以为此写一个特化版本,说这些函数都不重要。
  • 设计一个复数,有实部和虚部,不必为他写析构函数、拷贝构造函数、拷贝赋值函数,因为不写的话编译器有一个默认版本,那个版本所作的功能已经够了,复数的拷贝是一个位一个位拷贝,不需要特别做事情,不需要写析构函数,因为他马上就“死掉了”。复数没有指针,这些都不重要。


    type traits.png

    以下是type traits测试:


    type traits测试.png
  • 一个类带有指针一定要写析构函数,不带指针多半不用写。
  • 以下是测试结果,将string丢到里面,右边是一些类型的反馈,1代表是,0代表不是。


    type traits测试.png
  • 多态(polymorphic)类是一种有声明或者继承了虚函数的类。
  • 新版本不用像旧版本一样还要写偏特化版本来配合它。

那么type traits是怎么实现的呢,以is_void为例,它先要将const和volatile(多线程用到,易挥发)拿掉,用remove_cv函数实现,remove_const和remove_volatile各用一个泛化和偏特化版本的函数来使得传入的是否有const(volatile)都会去掉这两个。然后再进入_is_void_helper,如果是void那么传回真,如果不是则传回假,也是用泛化和偏特化。


type traits—is_void.png

四 cout

cout是一个类的对象,extern表示cout可以被外界看到,它能接受这么多类型是因为它作了大量的<<重载。如果你想写自己的类型,那么就要仿照写出<<的重载。


cout.png

五 moveable元素对于容器速度效能的影响

buf分别用moveable和non-moveable以insert的方式放进来,红黑树和哈希表的容器,你只要insert,那么它就会落在该落的地方,但是vector、list、deque你要insert必须要告诉它哪里insert。stl里的insert提供插入位置选择,但对于关联式容器,就算指定插入位置,如果不合理,他还是落在它应该落在的地方。

  • vector放三百万个元素,而拷贝构造函数却调用了七百多万次,是因为vector的成长是两倍两倍的,在成长的过程中引发拷贝构造。如果一开始指定有足够大的vector,就不会有这么大的拷贝构造。
    • moveable和non-moveable的效率差别很大
    • move copy和copy效率差别很大
  • list、deque、关联式容器放三百万个元素,拷贝构造也调用三百万次,这是因为他们不像vector是连续的内存空间。
    • moveable和non-moveable的效率差别不大
    • move copy和copy效率差别不大
  • 虽然list、deque、关联式容器一开始放元素moveable和non-moveable的效率差别不大,但是后来的操作也会影响。

下面是moveable class源代码,move其实是一种浅拷贝,不过他多了一个将原来的指针打断的操作。


moveable class源代码.png

moveable class 源代码.png

用move版本的条件是:move以后原来的东西不再使用。下图代码中V1type(buf)是一个临时对象,放进去以后就消失了,所以会调用move版本,而c1不是临时对象,c11(c1)时不会调用move版本。如果有信心可以调用move版本,那就可以像下面代码一样加上std::move,但是必须确保接下来不会再用到c1。

moveable测试.png
  • std::string有moveable版本的拷贝构造和拷贝赋值。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容