- 博客(104)
- 资源 (3)
- 收藏
- 关注
原创 【STL源码拆解】基于源码分析forward_lsit容器实现(详细!)
本篇文章介绍一下c++11中新增的顺序容器forward_list,基于stl的源码分析一下该容器的整体实现及数据结构。说明一下,我用的是gcc7.1.0编译器,标准库源代码也是这个版本的。按照惯例,还是先看一下本文大纲,如下:1. forward_list是什么forward_list是c++11为STL新增加的一种顺序容器,使用的时候包含头文件forward_list即可,真实的类声明位于头文件bits/forward_list.h中,类forward_list是一个类模板,基于单链表结构
2021-08-09 09:45:42
355
4
原创 c++11增加的变参数模板,今天总算整明白了
本篇文章介绍一下c++11中增加的变参数模板template<typename... _Args>到底是咋回事,以及它的具体用法。说明一下,我用的是gcc7.1.0编译器,标准库源代码也是这个版本的。按照惯例,还是先看一下本文大纲,如下:在之前写vector和deque容器源码剖析的过程中,经常发现这样的代码,如下:template<typename... _Args>void emplace_front(_Args&&... __args);可以
2021-07-29 09:43:47
1384
5
原创 【deque容器系列二】基于STL源码分析deque容器插入和删除时内存都是怎么变动的
上篇文章我们介绍了deque容器整体结构和构造实现,链接如下:基于STL源码分析deque容器整体实现及内存结构本篇文章接上篇,继续基于gcc中stl的源码剖析deque容器插入、删除、取值的实现原理,以提问者的角度去深入分析这些操作过程中发生了什么,并对deque容器适合使用的场景和使用时的注意事项进行说明。说明一下,我用的是gcc7.1.0编译器,标准库源代码也是这个版本的。按照惯例,还是先看一下本文大纲,如下:0. deque容器迭代器说明在正式开始讲述插入、删除等操作的实现前,我们
2021-07-16 12:32:10
414
24
原创 【deque容器系列一】基于STL源码分析deque容器整体实现及内存结构
本篇文章基于gcc中stl的源码介绍deque容器的整体实现和它的内存结构。说明一下,我用的是gcc7.1.0编译器,标准库源代码也是这个版本的。首先呢,还是看一下思维导图,如下:1. deque容器整体源码实现介绍deque容器是stl中顺序容器的一种,之前已经介绍过array和vector了,今天介绍deque容器,deque的本质是一个类模板,它的声明位于头文件bits/stl_deque.h,实现位于bits/deque.tcc,接下来我们就围绕这两个文件来介绍一下deque容器的实现
2021-07-14 11:37:00
330
8
原创 从c++标准库指针萃取器谈一下traits技法
本篇文章基于gcc中标准库源码剖析一下标准库中的模板类pointer_traits,并且以此为例理解一下traits技法。说明一下,我用的是gcc7.1.0编译器,标准库源代码也是这个版本的。还是先看一下思维导图,如下:1. 指针萃取器pointer_traits说明首先说明一下哈,官方并没有指针萃取器这个名称,其实pointer_traits是类模板,它是c++11以后引入的,可以通过传入的重绑定模板类型得到相应的指针类型,比较官方的描述是:pointer_traits 类模板提供标准化方法
2021-07-12 11:07:16
486
28
原创 【工欲善其事,必先利其器】之gdb五大高级用法
本篇文章讲解gdb的一些高级用法,在我们的开发生涯中,调试是很重要的技能,而在linux下开发,最常用的调试工具就是gdb了,所以这里介绍几种gdb比较高级的用法,助力我们的调试技能。还是先看下思维导图:1. gdb怎么调试多线程gdb调试多线程时,默认情况下是所有线程同时都在执行,但是假设我们想只有一个线程继续执行,其他线程都暂停呢?下面就来看一看该怎么实现这个功能。有这么一段多线程代码,如下://test.cpp#include <stdio.h>#include <p
2021-07-06 10:25:48
879
15
原创 【工欲善其事,必先利其器】之怎么查看c++代码生成的汇编代码
本篇文章讲解怎么得到c++代码对应的汇编代码,想要真正的理解一段代码到底是怎么执行的,还是要从汇编的层面去看,那怎么得到一段c++代码所对应的汇编代码呢,下面为你介绍三种方式。1. gcc编译生成XXX.s文件一般来讲,给你一个cpp文件,比如test.cpp,然后我们编译都是直接g++ test.cpp这样简单直接的方式,但其实它中间有很多个过程的,包含预处理、编译、链接等过程,而这其中的编译这个过程其实就是生成了汇编文件。比如对于一个cpp文件,我们执行下列命令:g++ -E test.cpp
2021-07-01 09:32:38
352
14
原创 上次说了静态数组可变长,今天知道原理了
之前发了一篇文章,讲c99变长数组的,链接如下:多年老c++程序员在静态数组这里翻船了发出去以后有了挺多的反馈,因为这并不是一个很难的知识点,所以如果接触过的自然而然是知道,但还真有挺多人表示不知道和不相信这个事,同时我上次也只是简单的说了一下这个事,没有去讲解这个变长静态数组的实现原理,今天补上。先看一下思维导图:1. 变长数组是长度一直可以变的吗变长数组,那么是长度一直可以变的吗,到底什么时候这个长度会确定下来呢?我们先看一下代码,如下:#include <iostream>
2021-06-29 09:17:00
587
6
原创 c++中引用面试点7连问以及引用真的不分配内存吗
本篇文章从面试官的口吻连问7个引用有关的问题,并且从汇编的层面上对引用进行深入分析,让你充分理解引用的概念和原理。首先还是看一下思维导图:1. 引用的背景和概念说到引用,首先要说一下’&'标识符,其实c语言中这个符号只是用来取地址的,并没有引用的概念,直到c++对这个标识符的作用进行了扩充,才有了引用这个概念。所谓引用,其实就是给变量取了一个别名,一个简单的例子如下:int main(){ int a = 2; int &b = a; return 0;}对于这段c
2021-06-28 09:25:36
1348
19
原创 c++类和继承面试点25连问
本篇文章连问面试时经常会遇到的类和继承相关25个问题,看看你能回答出几道题呀。还是先看一下思维导图,如下:1. c++的三大特性是什么c++的三大特性,说白了其实就是面向对象的三大特性,是指:封装、继承、多态,简单说明如下:封装是一种技术,它使类的定义和实现分离,也就是隐藏了实现细节,只留下接口给他人调用,另外封装还有一层意义是它把某种事物具现出属性和方法并形成了一个整体,就像一个人,同时具有身高和身体等等这些,才是完整的人,如果不封装,那这个人就相当于四分五裂了;继承,所谓继承,其实就是真实
2021-06-18 19:43:10
264
5
原创 c++头脑风暴-多态、虚继承、多重继承内存布局
本篇文章深入分析多态、虚继承、多重继承的内存布局以及实现原理。首先还是看一下思维导图:下面根据这个大纲一步一步的进行深入解析。一、没有虚函数时内存布局是怎样的1. 没有虚函数时类的内存布局一个类没有虚函数的时候,其实就是结构体,它的内存布局就是按照成员变量的顺序来的。看如下代码:#include <iostream>using namespace std;class CPeople{ double height; int age; char sex;public:
2021-06-17 09:13:55
427
原创 多年老c++程序员在静态数组这里翻船了
事情的起因事情是这样子滴,有一次我在代码评审的时候,发现有同事想使用运行时才能够获取到的值,去改变一个静态数组的元素个数,我当时就很诧异,因为我心里知道这样是不可行的,静态数组的元素个数在编译时就需要是固定不变的,一般只能是常量或者宏定义,否则编译就不能通过。但是当时我提出来以后,把原因说了,包括写出这个代码的人和另外一位同事都没理解,弄得我有点怀疑自己了,难道是我搞错了?我左思右想,最后我写了下面的代码来证实一下:#include <iostream>using namespace
2021-06-08 09:34:02
401
4
原创 三张图带你弄懂stl内存分配器,再也不怕面试官问了
本篇文章基于源码来剖析标准库中内存分配器的实现原理及使用。说明一下,我用的是gcc7.1.0编译器,标准库源代码也是这个版本的。还是来先通过思维导图来看一下本篇文章会从哪些方面来讲解stl中内存分配器和萃取器,如下:其实stl中有关内存申请的操作是包含两个内容的:内存分配器、内存萃取器。一、vector容器中对内存分配器的使用前面的文章中说了,vector容器本质上是个动态数组,它其实就是使用标准库的内存分配器实现的,还是先看一下代码,如下:template<typename _Tp
2021-06-04 19:29:18
638
原创 c++中typename、typedef以及using关键字用法
在c++的标准库中,因为类继承关系比较复杂和模板使用比较多的原因,源代码中充斥着typename、typedef和using这三个关键字,所以在继续剖析标准库源码之前,今天就来介绍一下这三个关键字的作用。一、typename关键字typename的第一个作用是用作模板里面,来声明某种类型,比如这样的:template<typename _Tp, typename _Alloc> struct _Vector_base;最开始的时候声明模板形参,也会使用class,但我们都知道c
2021-06-03 09:18:23
2133
4
原创 超详细STL之基于源码剖析vector实现原理及注意事项
本篇文章基于源码来剖析标准模板库中vector容器的实现原理及一些特殊注意事项。说明一下,我用的是gcc7.1.0编译器,标准库源代码也是这个版本的。多年以前面试的时候第一次被问到stl中vector的底层实现,那个时候的我真的很low,根本回答不上来,后来面试回来,在网络上搜索了一些vector底层实现,知道了它的底层是动态数组,但光知道动态数组是不够的,进一步的,动态数组写满了怎么办,它的实现用了c++的什么技术,一些特殊场景下怎么使用vector更有效率等等,这些极少有人讲清楚,今天我基于gc
2021-06-02 09:21:45
410
原创 写技术博客的一些想法,你我共勉
到今天为止,公众号也有了51篇原创文章了,其实里面2021年发布的只有18篇文章,其他的都是2019年发布的,尽管目前来讲,成绩还不好,但关于写技术文章,我也算有了自己的一些经验,今天就想从写作平台的选择、写作方式、写文章目的、技术文章内容选择、写文章应有的品德这五个方面说一下自己的一些经历和想法,大家共勉。一、写作平台的选择关于写作平台,我就我所使用过的所有平台都说一下我的看法:微信公众平台,也就是公众号,公众平台是一种私域流量,只有别人关注你以后才能看到你写的文章,如果没有人关注你,那你就是完全
2021-05-29 17:27:56
124
原创 题解5道c++面试题第一期(含解题思路、答案解析和实现代码)
本篇文章送上5道c/c++面试题目,并附上答案、解题思路以及扩展知识。1. 求下面函数的返回值#include <stdio.h>int func(int x){ int iCnt = 0; while(x) { iCnt++; x = x&(x-1); } return iCnt;}int main(){ printf("cnt = %d\n", func(9999)); return 0;}这题问的是函数的返回值,而通过代码我们能看到返回
2021-05-28 09:30:54
472
2
原创 作为一个有点小洁癖的程序员,不允许给我扣上抄袭的帽子
我之前写的一篇文章:libevent简单服务端和客户端实现实际上在知乎上2019年就发表过,链接如下:libevent简单服务端和客户端实现今天突然就收到一个评论:评论里面链接如下:评论里面的链接这个我就不能忍了,然后赶紧看了一下,原来虚惊一场,我是2019年9月4日在知乎发表的,评论里面这个链接是2019年9月30日发表的,而且人家注明了是转载于我的公众号,如下:The article is published in cpp gas station (ID:xy13640954449)
2021-05-26 17:35:28
96
1
原创 手写strcpy和memcpy代码实现
本篇文章聊一下strcpy和memcpy的代码实现,这两个也是c和c++面试中常考的问题点。1. 手写strcpy首先看一下,一份标准的strcpy的实现如下:char *strcpy(char* strDest, const char* strSrc){ assert( (strDest != NULL) && (strSrc != NULL)); char *address = strDest; while((*strDest++ = *strSrc++) != '\0')
2021-05-26 09:28:53
452
原创 c++编码规范
我的c++编码规范:属性 规则 例子 全局常量类应用(枚举、宏) 全大写英文单词组合用下划线分隔 DATA_SIZE 函数命名 第一个单词首字母小写,后面全部首字母大写(或者全部首字母大写,看整体吧) initData()/InitData() 类名 C开头,后面全部首字母大写 CTestObject 接口名 I开头,也是全部首字母大写 ITestObject 类的成员变量 m_开头,首字母大写英文单词组合 m_
2021-05-21 12:35:49
133
原创 超详细STL之array容器使用及实现原理解析
说明一下,我用的是gcc7.1.0编译器,标准库源代码也是这个版本的。本篇文章讲述STL中array的使用及原理。导读array其实是一个固定大小的数组,元素类型及大小在声明的时候指定,原型如下:template<typename _Tp, std::size_t _Nm> struct array { ... };有些书上说array也是一个class,但是我这个版本看到的是struct,不过没有关系,除了一些细微的方面,struct和class.
2021-05-21 09:25:45
1260
原创 c++中lambda表达式用法
说明一下,我用的是gcc7.1.0编译器,标准库源代码也是这个版本的。本篇文章讲解c++11中lambda表达式用法。初次接触lambda这个关键字,记得还是在python里面,但其实,早在2011年c++11推出来的时候我们c++就有了这个关键字啦。lambda表达式是C++11中引入的一项新技术,利用lambda表达式可以编写内嵌的匿名函数,用以替换独立函数或者函数对象,并且使代码更可读。所谓函数对象,其实就是对operator()进行重载进而产生的一种行为,比如,我们可以在类中,重载函数调用.
2021-05-20 10:02:35
1774
1
原创 最全面的c++中类的构造函数高级使用方法及禁忌
说明一下,我用的是gcc7.1.0编译器,标准库源代码也是这个版本的。本篇文章讲解c++中,构造函数的高级用法以及特殊使用情况。1. 拷贝构造和移动构造区别对于拷贝构造和移动构造,还是看一下这段代码:#include <iostream>#include <string.h>using namespace std;class CPtr{ private: char *m_pData; int m_iSize; public: //without .
2021-05-14 09:19:58
705
原创 c++类的构造函数不显式声明会自动生成吗
说明一下,我用的是g++7.1.0编译器,标准库源代码也是这个版本的。本篇文章讲解c++11中,类的构造函数种类,以及不显式声明的情况下是否会自动生成。1. 类的构造函数类别在我刚接触c++的时候,我一直知道类可以有四种形式的构造函数,即无参构造函数、有参构造函数、拷贝构造函数、赋值运算符构造函数,最近看标准IO源代码,发现又多了一种,那就是移动构造函数,这是c++11中补充进来的,所以现在c++可以拥有四种形式的构造函数,即无参构造函数、有参构造函数、拷贝构造函数、赋值构造函数、移动构造函数、移.
2021-05-13 09:14:41
802
原创 c语言中strstr函数的一个注意点
今天说一个之前工作上遇到过的一个问题,也是之前没注意过的一个点。先看一段代码:#include <stdio.h>#include <string.h>int main(){ char sz1[16] = {0}; char sz2[10] = {0}; char sz3[3] = {0}; strncpy(sz1, "bbAAcc", sizeof(sz1)-1); strcpy(sz3, "AA"); if ( strstr(sz1, sz2) != NU
2021-05-11 09:26:10
284
原创 探究一下c++标准IO的底层实现
说明一下,我用的是g++7.1.0编译器,标准库源代码也是这个版本的。本篇文章讲解c++标准IO的底层实现结构,以及cin和cout的具体实现。在看本文之前,建议先看一下之前的一篇文章,至少要知道标准IO里面各个类之间的关系:c++标准输入输出流关系梳理1. 标准IO的底层结构通过通读c++标准IO的源代码,我总结出了它的底层实现结构,如图:它分为三层结构:外部设备、缓冲区、程序,说明如下:外部设备是指键盘、屏幕、文件等物理或者逻辑设备;缓冲区是指在数据没有同步到外部设备之前,存放数.
2021-05-10 09:49:45
480
1
原创 libevent简单服务端和客户端实现
1.生成动态库说明在开始使用之前,我们需要先搞清楚libevent编译生成的各个动态库的作用。在下载libevent源码包进行编译以后,当前目录生成.libs目录,该目录下是所有的目标文件,这里我们只说明个动态库so文件的作用,通过makefile我们可以知道各个动态库包含内容:动态库名称作用libevent_core.so这个库包含了所有核心的事件和缓存功能libevent_extra.so这个库包含外围的dns、rpc、http等协议使用libevent.so
2021-05-06 11:36:17
542
原创 libevent定时器是怎么实现的
1. 定时器是怎么实现的在之前的文章里我们讲过,libevent最后处理都是在event_base_loop调用了相应的dispatch函数,定时器也是在dispatch函数中处理的。还是以epoll为例,在epoll_dispatch函数有以下一段代码: if (tv != NULL) { timeout = evutil_tv_to_msec_(tv); if (timeout < 0 || timeout > MAX_EPOLL_TIMEOUT_MSEC) { /* L
2021-05-06 11:35:34
469
原创 libevent绑定、监听和读写数据
1. 绑定和监听在上一篇文章中,以epoll为例说到了事件机制,会按顺序调用init和dispatch这两个回调函数,但是,我们回忆一下网络编程的过程,首先是需要创建socket、绑定socket、监听socket的,但目前为止还并没有涉及到,再去看源代码,会发现里面有listener.c,这个文件里面就会去做创建socket的过程。看evconnlistener_new_bind函数,如下:struct evconnlistener *evconnlistener_new_bind(struct
2021-05-06 11:34:51
595
原创 libevent的事件机制
1. 事件初始化从上一篇文章《libevent是怎么选择底层实现的》可以看出来,调用event_base_new()函数就是初始化好底层实现,给event_base结构体中evsel赋值,evsel是一个eventop结构体,我们再来看下:struct eventop { /** The name of this backend. */ const char *name; /** Function to set up an event_base to use this backend. It sh
2021-05-06 11:32:49
212
原创 libevent是怎么选择底层实现的
1. libevent到底使用哪种io模式来作为底层实现libevent实际封装了很多IO复用模式,比如evport,select,poll,epoll,devpoll等等,这些都是不同操作系统下的I/O多路复用模式,那么我们怎么知道当前使用的是哪种模式呢?说到底层实现,那就不得不说说event-config.h文件的生成。1.1 event-config.h文件的生成在上一篇《libevent目录结构分析》中,我们提到event-config.h,它存放了很多宏定义配置。event-config
2021-05-06 11:31:21
135
原创 c++标准库流状态一览
1. 流状态说明c++标准库对于流定义了一套它自己的状态变化规则,在ios_base.h声明的ios_base类中,它定义了一个枚举类型_Ios_Iostate来表示流状态,主要有以下四种:状态说明badbit在输入输出时遇到了系统级错误,会置为badbiteofbit读取文件时读到了文件末尾,就会置为eofbitfailbit往流缓冲区写入或者读取数据发生错误时,会被置为failbitgoodbit上面三种都没有时,就是goodbit另外ios_ba
2021-05-06 10:54:23
1488
4
原创 c语言结构体字节对齐详解
1.什么是字节对齐在c语言的结构体里面一般会按照某种规则去进行字节对齐。我们先看一段代码:struct st1{ char name; double age; char sex;};//32位下 sizeof(struct st1) = 16//64位下 sizeof(struct st1) = 24struct st2{ char a; char b; char c;};//32位和64位下, sizeof(struct st2)都是3个字节从以上结果可以看出,结构体
2021-05-06 10:40:17
777
原创 c++中explicit和mutable关键字探究
今天说一说c++里面的两个关键字explicit和mutable。1. explicit关键字在写c++标准输入输出相关文章,查看iostream实现代码的时候,经常看到构造函数前面带有explicit关键字,那么它到底有什么作用呢。explicit用来防止由构造函数定义的隐式转换,先看这样一段代码:#include <iostream>class Base{private: int a;public: Base(int p_a){ a = p_a;}
2021-05-06 09:17:06
292
4
原创 c++中endl操作符以及它的兄弟们
说明一下,我用的是g++7.1.0编译器,标准库源代码也是这个版本的。一直以来,我们每次使用cout输出数据的时候,如果要换行,都知道使用形如cout << endl;这样的形式,那么endl到底是什么呢,它是怎么样实现输出一个换行符的功能的,以前我没有思考过,但现在我想弄懂它,下面就一起看一下吧。1.endl操作符的实现在标准库头文件<ostream>中,我找到了endl的操作符重载函数,如下:template<typename _CharT, typename .
2021-04-30 09:31:11
2864
原创 c++中ifstream及ofstream超详细说明
前文说过,ifstream是继承于istream,ofstream是继承于ostream,fstream是继承于iostream类,而他们使用的缓冲区类是filebuf。关于这些类之间的关系,有兴趣可以去查看我之前的文章:c++标准输入输出流关系梳理1. filebuf类介绍filebuf类又比stringbuf类要复杂一点,毕竟是对文件进行读写,首先在它的成员变量中找到了这样一条声明:__file_type _M_file;_M_file就是它里面的文件操作对象,那么探究一下__file
2021-04-28 09:28:34
2475
原创 c++中istringstream及ostringstream超详细说明
文章目录1. stringbuf类介绍1.1 stringbuf类构造函数1.2 str函数2. istringstream类2.1 rdbuf函数2.2 swap函数3.ostringstream类和stringstream类前文说过,istringstream是继承于istream,ostringstream是继承于ostream,而他们使用的缓冲区类是stringbuf。关于这些类之间的关系,有兴趣可以去查看我之前的文章:c++标准输入输出流关系梳理1. stringbuf类介绍string
2021-04-26 10:01:17
2230
2
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人