![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
C/CXX
劲蜡鸡腿堡
这个作者很懒,什么都没留下…
展开
-
next_permutation,prev_permutation源码分析
next_permutaion伪代码伪代码描述如下,这里只阐述主要步骤,不对异常进行处理// last 表示 A.size() - 1// 1: 从后向前遍历,获取第一个非递增点for i -> last - 1 to 0 if A[i] < A[i + 1] break // 2:从递增序列中找到第一个必A[i]大的元素for j -> last to i + 1 if A[j] > A[i] break// 3、交换swap(A[i], A[j])原创 2020-09-07 19:56:43 · 296 阅读 · 0 评论 -
insert_iterator分析
insert_iterator为迭代器适配器,用于封装传统迭代器来提供更为丰富的功能。insert_iterator内部维护了两个变量:_Container* container :指向插入的目标容器_Container::iterator iter:插入位置记录其实质上就是调用container->insert源码分析如下: template<typename _Container> // _Container 表示传入的容器类型 class insert_i原创 2020-09-05 19:01:15 · 451 阅读 · 0 评论 -
STL _Hashtable源码分析
_HashtableSTL中并没有提供直接提供hashtable,而是通过将其封装为unordered_map和unordered_set来供外部使用,也可以说它们是由_Hashtable来实现的。其_Hashtable的结构如下,其与传统的hash list有相同点但也存在些许不同。同:_M_buckets为nodes指针数组,其保存了node的地址。而nodes中主要保存了2个元素,分别为next指针和value。增删改查过程基本相似,主要分为两个步骤。首先计算hash(key),获取的bu原创 2020-09-01 17:14:43 · 587 阅读 · 2 评论 -
map源码分析
map可谓是最经常使用的关联容器,其实现同样基于红黑树。我们知道红黑树中一个节点保存一个value,其并没有明显的key,value概念,其在插入时比较的是value值的大小。因此我们需要对value和value的compare做一点小小的修改,这样便可以通过红黑树实现这种key,value的关联。其实现过程类似如下代码:我们将map的key, value作为一个整体setvalue,此setvalue便是set的value,之后重定义setvalue的compare行为,使其只比较key,经过这样的修原创 2020-08-19 16:21:28 · 575 阅读 · 0 评论 -
set源码分析
set是一个关联容器,其内部保存了一系列唯一的且排序的key对象。其内部实现是通过红黑树来完成的,对于红黑树其为带有自平衡功能的二叉搜索树BST。因此,其内部元素有序(BST的中序遍历将会获得一个有序序列)且其可以在log时间内查找相关节点。containerset实质上就是红黑树的包装类而已,查看定义可以获取相关信息。其包含数据成员_M_t,此数据成员就是红黑树,之后所有的操作都是对其进行set::iterator就是_Rep_type::const_iterator template&l原创 2020-08-19 11:36:15 · 199 阅读 · 0 评论 -
multiset源码分析
set是一个关联容器,其内部保存了一系列排序了的不重复的类型为key的对象,其排序使用构造时传入的compare函数。其插入、删除、查找在log时间复杂度内完成。在STL中其使用红黑树来实现此结构,对于红黑树这里不多做介绍,其实质上就是带有平衡功能的二叉排序树,所以说红黑树的中序遍历有序,其属于二叉树。containerset的实现就是借助红黑树实现,在如下定义中,我们可以看到如下信息其定义了_Rep_type _M_t这一数据成员变量,其类型为typedef _Rb_tree<key_typ原创 2020-08-19 10:43:57 · 467 阅读 · 0 评论 -
array源码分析
array容器封装了一个固定大小的数组,其语义上等价于一个struct,其内部只封装了T[N]作为其唯一成员。这样便可以既拥有C-style数组的性能也拥有标准容器的便利性。其实现等价于如下template<typename _Tp, std::size_t _Nm>struct array { _Tp _M_elems[_Nm];}我们都知道标准容器在内存分配中采用的方式为alloc内存分配器分配,其从根本上来说都是调用动态内存分配。那么这种内存分配方式就存在性能损耗,我们程序运原创 2020-08-18 18:52:51 · 530 阅读 · 0 评论 -
forward_list源码分析
forward_list是一个单链表的实现,相较于list,其有更高的空间存储效率,但是其迭代器只能进行单向移动。其构造如图所示:与list进行比较可以发现,其头部节点不再存储任何数据并且结构体中也没有开辟空间来存储forward_list的大小,所以其并没有实现size()这个成员函数,即我们无法在O(1)的时间内获取forward_list大小。其尾部节点并没有指向头部节点,其指向的为nullptr,这样做能有效保证其迭代器的单向性。_Fwd_list_node_Fwd_list_node继原创 2020-08-18 17:27:20 · 451 阅读 · 0 评论 -
list源码分析
list是CPP对双向链表的实现,其结构相对于传统的链表结构并无太大差异。CPP的实现将第一个节点设置为头节点,其存储的元素类型为size_t,用于存储list链表中数据元素的个数。其后的节点才是真正存储数据的节点。并且其为快速定位头部尾部且同一插入删除操作,其定义为循环链表。其结构示意图如下_List_node_List_node是链表中节点的定义,其包含三个元素,分别是传统previous指针、next指针、存储元素_Tp。其中previous指针、next指针是基类_list_node_bas原创 2020-08-18 15:09:26 · 370 阅读 · 0 评论 -
Deque源码分析
deque在实现时使用一连串固定大小的数组和一个书签来实现,其结构图如下:假设此时我们存储的数据类型为T,那么Nodes数组中存储的类型便为T*,即T[]的位置。而T[]则是实际存储数据的内存位置。这种结构在empty()时,其Nodes下不会挂载任何数组,当我们需要插入元素时,会在Nodes的中间开始挂载而不是两端进行。这样便保证了deque可以进行两端的任意插入操作。插入操作时,会先判断当前数组是否还有剩余空间,如果当前数组还剩余空间则在数组空间内placement construct,否则我们需要申原创 2020-08-16 15:53:06 · 281 阅读 · 0 评论 -
vector源码分析
这里引用源码中的一段描述In some terminology a %vector can be described as a dynamic C-style array, it offers fast and efficient access to individual elements in any order and saves the user from worrying aboutmemory and size allocation.vector毫不夸张得说就是有动态内存分配功能的传统数组原创 2020-08-14 21:53:09 · 1082 阅读 · 1 评论 -
weak_ptr和shared_ptr功能总结
结构分析weak_ptr和shared_ptr都包含一个_M_refcount数据成员,追溯其定义,内部包含一个_Sp_counted_base<_LP>* _M_pi。shared_ptrshared_ptr能够实现其功能依赖于对于多个shared_ptr只实例化一个_Sp_counted_base<_Lp>。当我们通过某一shared_ptr初始化另一shared_ptr时,其会执行如下两个步骤1、this->_M_ptr = other->_M_ptr原创 2020-08-09 15:57:45 · 1022 阅读 · 0 评论 -
weak_ptr源码分析
在经历过shared_ptr源码分析之后,我们接下来继续分析weak_ptr。weak_ptr是作为shared_ptr的补充而出现的,用于避免循环引用问题。weak_ptr结构与shared_ptr近乎一致,这里直接写出部分结构和关键函数。weak_ptr<_Tp>继承自__weak_ptr<_Tp>,其主要功能都在__weak_ptr<_Tp>中实现。__weak_ptr包含数据成员element_type* _M_ptr;和__weak_count<原创 2020-08-09 11:05:56 · 532 阅读 · 0 评论 -
shared_ptr源码分析
shared_ptr是从C++11开始提供的智能指针,用于管理多个指针对同一实体的资源释放问题,保证在多个指针指向同一实体时,仅最后一个指针解除指向时才会释放资源。shared_ptr构造shared_ptr<_Tp>继承自__shared_ptr<_Tp>,其功能主要由其实现。让我们以单值构造函数为切入点开始分析。 template<typename _Yp, typename = _Constructible<_Yp*>> explici原创 2020-08-08 23:09:45 · 1944 阅读 · 2 评论 -
pair笔记
pairpair是一个struct 模板,其定义如下template< class T1, class T2> struct pair;从中我们可以看出其实现依靠struct。从使用方面进行考虑,其为programmer提供了方便的使用,我们不必为每次使用一个简单的二元struct而专门定义一个struct自定义类型,而是交由编译器自动实现。相较于其他容器,如vector<>。其利用struct实现,所以其内存占用栈空间,不用在运行时申请地址空间。所以其在原创 2020-07-20 22:23:37 · 129 阅读 · 0 评论 -
priority_queue使用
priority_queue分析priority_queue是容器适配器,并不是容器。其并没有单独实现任何容器相关功能,而是在现有容器的基础上进行了再封装而已。参照如下源代码我们不难看出,其实现依靠了algorithm库相关与heap的操作 // stl_queue.h push方法 void push(value_type&& __x) { c.push_back(std::move(__x)); std::push_heap(c.begi原创 2020-07-20 16:59:50 · 166 阅读 · 0 评论 -
chrono库笔记
chrono库主要包含clocks、time point、duration三个主要类型。durationduration为一个模板类,表示时间间隔,其定义如下:template<class Rep, class Period = std::ratio<1>>Period表示一个时钟滴答周期,每当经过一个Period秒时,其Rep类型的滴答总数就会执行count + 1。在日常使用中Rep可以为整数或者浮点数,Period使用标准库中的分数模板ratio进行表示。durat原创 2020-07-16 17:28:27 · 591 阅读 · 0 评论 -
CPP虚函数分析
#include <iostream>#include <string>using namespace std;/* *关闭内存对其,我们能够看到类实际的空间大小 *(从中我们可以看出,不光是结构体存在内存对齐,类也存在内存对齐) */#pragma pack(1)class A{private:public: int a; A()...原创 2020-03-05 19:03:33 · 307 阅读 · 0 评论 -
C语言实现容器
实现思路最近在看Redis源代码,发现了许多自己不知道的C语言的书写方式,这些写法可以实现许多结构。CXX使用泛型提供了容器,但是C语言中不允许将数据类型作为参数进行传递,所以我们必须使用另一种方式来实现我们的目的结构。typedef struct listNode { struct listNode *prev; struct listNode *next; voi...原创 2020-01-14 19:13:49 · 3116 阅读 · 0 评论 -
可变参数
可变参数C语言中printf (const char *__restrict __fmt, ...),中fmt是格式化字符串用于控制输出,而...便是可变参数,它可以接受任意数量,任意类型的参数,是一种灵活的函数调用形式。当用户想要解析传递的可变参数时,他需要包含stdarg.h头文件,以使用其内部定义的解析函数。其定义的函数如下: #define va_start _crt_va_st...原创 2020-01-08 21:40:38 · 179 阅读 · 0 评论