C++之STL
STL体系结构与内核分析
weixin_39770712
这个作者很懒,什么都没留下…
展开
-
侯捷C++ STL体系结构与源码剖析:关于moveable的说明
vector体积二倍增长,需要挪到另外一个空间进行构造,所以虽然insert进行300万次,而构造的动作有700多万次。list一个萝卜一个坑,所以构造的次数和insert一样。一个一个节点式的容器在时间花费上差不多,只有vector例外。move的工作和浅拷贝的原理差不多。传进去的参数是reference_by_reference。copy版本会真的分配,而move版本只是拷贝指针。...原创 2020-11-15 21:57:18 · 418 阅读 · 0 评论 -
侯捷C++ stl体系结构与源码剖析:traits(萃取器)的实例及底层实现
G2.9版本,这个版本实用性不高。trivial是不重要的意思,回答是false,默认都是重要的。要是不赞成这样,可以特化,比如来特化int类型。自己的类型要自己定义重要不重要。typedef都是来回答问题的。一般重要是存在指针的场合,防止系统默认进行一些浅拷贝,这个时候可以令拷贝构造变成重要的,就是不采用系统默认的拷贝构造。C++11版本:现在的版本不用自己申明重要不重要,系统自己考虑。测试程序:来回答问题。string的测试:注意回答是1的部分。Foo类中只有数据,没有函数,所以和以原创 2020-11-15 11:00:43 · 306 阅读 · 0 评论 -
侯捷C++ stl体系结构与源码剖析:tuple底层实现详解(递归继承)
tuple,一堆东西的组,元组。它可以指定任意的元素,任意的类型,形成一个结构体。注意下面tuple的声明和定义,用法。make_tuple可以直接把值放进去,类型编译器会实参推导。tuple还可以比较大小,如果是同一类型就逐一比较。tie(i1,f1,s1)=t3是将t3的元素都拿出来,然后附着到那三个变量上,连续赋值。还能够使用tuple_element<1,TupleType>::type拿出1号元素的类型出来。底层实现:用到了可变参数模板。可变参数模板都是一个主题加一个终止,来原创 2020-11-15 09:53:06 · 542 阅读 · 0 评论 -
侯捷C++ stl体系结构与源码剖析:一个万能的hash function
为一个类,构建一个Hash Function。有两个办法,一是设计为成员函数,但是为了调用成为函数对象,需要重载operator();二是设计成普通函数。第二种方法中,<>中第二个模板参数是函数类型,创建时还要将真正的函数地址放进来。将各种基本元素类型的hash组合起来,std::hash< std::string>()是一个对象,可以当函数来使用。typename… Types任意多的模板参数,可变参数模板。函数1和函数2,函数3的区别是第一个模板参数的类型不一样,虽然同名函原创 2020-11-14 16:46:47 · 330 阅读 · 0 评论 -
侯捷C++ STL体系结构与源码剖析:迭代器对算法的影响
distance函数,要看传入迭代器的类型,如果是连续空间直接相减,否则只能++。萃取器iterator_traits要根据输入迭代器类型来确定返回类型。加入last和first相差100万,则第二个直接一减就出来,而第一个要走100万步。向上继承,调用最匹配的父类。假设传入的是farward_iterator_tag类型,则调用input_iterator_tag。再来一个栗子:copy函数:源端需要起点终点,而目的端只需要起点。这里主要是为了实现加速,才那么多特化。for-loop是最慢的,从来原创 2020-11-12 22:09:54 · 112 阅读 · 0 评论 -
侯捷C++ STL体系结构与源码剖析:迭代器适配器详解,reverse_iterator,inserter,ostream_iterator,istream_iterator
迭代器适配器:为了修饰迭代器那么内部需要一个迭代器,即current。关键部分:current不能改变.reference operator*() const { Iterator tmp=current; return *--temp;}原创 2020-11-13 23:23:40 · 140 阅读 · 0 评论 -
侯捷C++ stl体系结构与源码剖析:函数适配器详解,C++11新特性bind
函数适配器,是去修饰函数,然后还要表现出函数的性质。所以最终还是要重载(),以表现出函数。binder2nd来绑定第二个参数,之前less是x<y,现在是x<40。less< int>()是创建了一个函数对象,不是调用。bind2nd调用了binder2nd,那么最终的效果是less< int>()传进去变成op,40传进去变成value。bind2nd调用过程,重点: 当执行pred(*first)调用的是operator()这个小括号重载函数,才真正调用了le原创 2020-11-13 22:24:43 · 190 阅读 · 0 评论 -
侯捷C++STL体系结构与源码剖析:标准库的算法实例
accumulate函数:第一个版本是累加,第二个版本是累计某个操作。()叫做function call operator,函数调用操作符,我们要传进去能调用()的东西。可被调用的东西,包括一般的函数myfunc,或者function object函数对象,它是一个类或者结构体,并重载小括号()所产生的对象。其实函数对象就是仿函数。for_each:一个区间里,对每一个元素做一件事情。replace,replace_if,replace_copy:元素如果等于旧值那么就被取代为新值;if就代表传一个原创 2020-11-12 23:06:26 · 204 阅读 · 0 评论 -
侯捷C++STL体系结构与源码剖析:cout的底层原理剖析
cout是一个ostream类对象extern表示这个文件之外也能用cout。重载了很多类型,operator<<。这些都是常见的类型。要不是基本的类型,需要在自己定义的类中,进行操作符重载operator<<。这是标准库里的,粉红色的那些类型都是我们可以直接拿来cout的,但是都是在各自的类重新进行操作符重载了。比如complex复数的输出,就是在自己的类中重新定义,输出格式:<实部,虚部>...原创 2020-11-11 20:30:03 · 760 阅读 · 0 评论 -
侯捷C++STL体系结构与源码剖析:适配器原理大解剖
适配器,改造器更为贴切。换肤工程,小变化。出现在三个地方,仿函数、容器、迭代器的适配器。为了实现一个桥梁的作用,就是A代替B给大家使用,但是底层是A调用B。这里的关系是复合(拥有的关系),不是继承。所以迭代器适配器内含了一个迭代器,容器适配器内含了一个容器。为了实现仿函数适配器与仿函数之间的回答与提问。必须包括三个typedef。容器适配器的栗子:这边的改造也可以这样:内含一个deque,它本身有100个函数,但是只用到6个,改函数名称等这都算是一种改造。...原创 2020-11-11 20:01:59 · 108 阅读 · 0 评论 -
侯捷C++STL体系结构与源码剖析:仿函数剖析
仿函数(functors,别名function object)是我们最容易自己写,然后融入标准库的部件。只为算法服务。仿函数要模仿函数,必须重载operator(),并且是个class。由此产生的对象称为函数对象,或者叫仿函数(是一个对象,像一个函数)。仿函数应用:less< int >是一个类型,加一个(),生成一个临时对象。这里自己定义的myclass没有继承关系,那就没有融入STL体系结构中。继承了就能被适配器(adaptor)去修饰和改造。仿函数需要继承的东西。他们的大小是1原创 2020-11-11 19:40:43 · 128 阅读 · 0 评论 -
侯捷C++ STL:迭代器的分类
STL六大部件的关系:array,vector,deque是random_access_iterator_tag;list,红黑树(set/multiset,map/multimap)是bidirectional_iterator_tag;forward_list是farward_iterator_tag;而hash(unordered set/multiset,unordered map/multimap)要看底层是单向还是双向。连续空间可以跳,不连续空间不能跳。typename加上(),会生成原创 2020-11-10 22:37:23 · 109 阅读 · 0 评论 -
侯捷C++ STL体系结构与内核分析:map/multimap的实现(红黑树的应用)
map/multimap的基本功能:底层实现:通常我们使用者只要放前两个参数。注意const。其他编译平台:select1st重载了(),叫做仿函数(函数对象)。传进去pair,传出first。一个栗子:map独特的operator[]由key找data,找到就返回。如果没有就让该key对应一个默认的data值。又一个栗子。对比放入新元素,multimap要自己配pair,而map可以使用[]。但是[]要先搜索,然后insert,速度上比不了直接插入pair。...原创 2020-11-09 22:07:56 · 218 阅读 · 0 评论 -
侯捷C++ STL:哈希表(unordered_set,unordered_multiset,unordered_map,unordered_multimap)的底层实现
哈希表的产生由于内存不够一一映射。于是乎在空间不足时取余数。为了防止某一个链表过长,这里根据经验来制定规则。当插入的元素个数等于buckets时这时哈希表要扩容。扩容因子是两倍。但是buckets值尽量是质数,选择质数是为了尽量做到均匀散列。所以扩容后要找两倍大后附近的质数。编译器将空间扩容的空间大小都自己定义好了,不用重新计算空间,53-97-193…。底层实现:HashFcn:一个对象如何映射为一个号码/编号。hasher,key_equal,ExtractKey是function objec原创 2020-11-09 21:32:57 · 920 阅读 · 1 评论 -
侯捷C++之STL:set、multiset的底层实现(红黑树)
基本功能:底层实现我们只要指定set的第一参数,第二第三参数是默认的。const_iterator迭代器可以指向这个元素,却不能改变这个元素。由红黑树实现,可以说得上set是个适配器。在其他编译器的实现:例子:...原创 2020-11-09 08:06:47 · 966 阅读 · 0 评论 -
侯捷C++之STL:红黑数的底层实现
关联式容器查找非常快,插入也很快。key_compare理论上是1个字节(由0变1),他不含任何内存。然后是对齐。head也是刻意放进去的。下面是一个例子,其中value类型是int,表示一个value没有data部分。KeyOfValue表示如何从value中取出key。这里identity是传啥进去就返回啥,本身的意思。测试:新版本:其中_M_color是一个枚举类型。...原创 2020-11-09 05:20:00 · 181 阅读 · 1 评论 -
侯捷C++ STL 体系结构与内核分析:deque的实现(源码剖析)下,stack及queue的实现
常见的函数:操作符重载:后++调用前++,注意到达临界点。+=操作。新版本:和deque息息相关的queue,stack。这俩都是内含一个deque,并封锁其一些功能。这俩是适配器。替代方案:可以用list实现stack,queue.但是deque更快一点 。关于用vector实现...原创 2020-11-09 03:54:10 · 171 阅读 · 1 评论 -
侯捷C++ STL 体系结构与内核分析:deque的实现(源码剖析)上
buffer是缓冲区,五个缓冲区需要串接起来。连续是假象,分段是事实。 deque的迭代器是一个class,内部有四个元素:cur,first,last,node。其中node指向控制中心,控制中心是一个vector实现的,控制中心++会跳到下一个缓冲区。first,last是同一块缓冲区的头和尾,前闭后开。iterator的大小为4个指针。...原创 2020-11-07 18:56:40 · 147 阅读 · 0 评论 -
侯捷C++STL 体系结构与内核分析:array、forward_list的实现
array把原来c语言的数组包装成容器。不可扩充,必须指定大小。直接把指针当迭代器。end指向最后一个元素的下一个地址。不解引用就没问题,关于end。forward_list的实现原创 2020-11-05 21:48:12 · 117 阅读 · 0 评论 -
侯捷C++STL 体系结构与内核分析:vector的实现
当内存不够,会从内存中寻找另外一个空间,并以二倍内存的大小增长。vector本身就三个指针大小,start,finish,end_of_storage三个指针。finish取不到,前闭后开。重点:扩容原理这里调用insert_aux还要检查一下是否有空余的空间,是防止其他函数的调用。vector扩容其实不需要在重复检查。无备用空间情况:分配了两倍空间后,先拷贝,再构造新的元素。vector的迭代器萃取器可以得到那5个元素:value_type,difference_type,pointer原创 2020-11-05 21:26:57 · 177 阅读 · 0 评论 -
侯捷C++STL 体系结构与内核分析:深度探索list(下),GCC4.9和GCC2.9对比
iterator参数由原先的三个变成一个,指针由void变成_List_node_base,指向了同一个class。对于迭代器begin,和end的实现。该链表是环状,但是最后有一个空白节点,end指向这个。sizeofGCC版的list是8,是因为里面有两个指针,即_M_next和_M_prev。...原创 2020-10-31 19:13:20 · 252 阅读 · 0 评论 -
侯捷C++STL 体系结构与内核分析:深度探索list(上),list的结构及迭代器
list的底层实现:list只有一个元素node,其类型是list_node*,是一个指针,在32位系统中取sizeof为4。list_node是一个节点。在节点的定义里,第一句typedef void* void_pointer;指针指向void,会转型。链表的存储不是连续空间,所以不能用普通指针类型的迭代器,++指针肯定不会指向下一个链表的位置。此处的迭代器(除了vector以外的容器迭代器都是class)是一个class。它重载了指针的很多功能。具体细节如下图:所有容器的迭代器必须要做5原创 2020-10-31 17:28:01 · 189 阅读 · 0 评论 -
侯捷C++STL 体系结构与内核分析:容器的结构与分类
各个容器的数据结构的形式:继承是is-a的关系;复合是has-a的关系。原创 2020-10-31 15:32:22 · 100 阅读 · 0 评论 -
侯捷C++STL 体系结构与内核分析:分配器allocators、及alloc的出现
STL中各个容器的第二个模板参数都会调用allocator。allocator中两个最重要的函数是allocate和deallocate。allocate最终会调用operator new。operator new底层调用malloc,malloc分配的空间如下图原创 2020-10-31 10:56:20 · 287 阅读 · 0 评论 -
侯捷C++STL 体系结构与内核分析:面向对象编程VS泛型编程
面向对象编程试图将数据、方法整理在一起。泛型编程则相反,试图将数据和方法分开。泛型编程的数据和方法可闭门造车,各干各的,分开开发。所有算法都涉及到元素比大小,会用到操作符重载或者自定义函数。...原创 2020-10-27 21:42:52 · 93 阅读 · 0 评论 -
侯捷C++STL 体系结构与内存分析:容器vector测试
vector的测试程序:#include <vector>#include <stdexcept>#include <string>#include <iostream>#include <ctime>#include <cstdio> // snprintf()#include <cstdlib> // abort()#include <algorithm>namespace jj02原创 2020-10-25 17:34:32 · 103 阅读 · 0 评论 -
侯捷C++STL 体系结构与内核分析:容器-结构与分类、array测试
红色框起来的是C++11增加的东西,array由语言的数组包装成class。Sequence Containers(序列式容器),会按放进去的顺序排列array要多大有多大,严格限定的大小。vector起点不能动,后面可以自动增长,分配器可以自动扩充。deque,两端可进可出,前面和后面都可以扩充。list,链表,指针串起来,双向的,环状链表。forward-list,单向链表,放一个分配一个。Associative Containers(关联式容器),有key/value,基于红黑树。各家编译器.原创 2020-10-25 16:38:38 · 194 阅读 · 0 评论