自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(74)
  • 收藏
  • 关注

原创 解决Xcode中文代码乱码的问题

在网上搜索的资料基本都是批量打开后再进行保存,在代码文件量比较多的情况下这种方式的效率不高。因此还是需要选择编辑器自带的方式来统一修改打开文件时候的编码方式。最后选择根据实际情况选择convert或者reinterpret即可。

2023-02-02 17:19:28 1860 1

原创 Git学习:工作流学习实践

在实践的项目开发过程中,会使用Git或者类似的版本控制工具来管理代码。下面介绍基于Git工具在实际项目开发过程中的使用流程。如上图所示显示了项目开发的一个简化流程。在开发一个新需求/版本的时候,一般会从主分支main中拉出一个新的dev分支来进行开发。等开发全部完成之后再进行合并进main中。在实际工作中我们个人会在dev的基础上再创建一个新的分支进行开发。如果代码经过评审(code review, CR)没有问题的话就可以由项目负责人合并进入dev分支。基于此,下面模拟一下实际的开发流程。

2023-01-07 15:45:52 730

原创 Git学习:各阶段回退方法

在把一份代码完成之后发送到 “远程仓库”,可能中间还经历了不同的 “提交阶段”。回退本地版本,然后把旧的版本重新push上去。然而,此时的问题就是此时本地的版本落后于远程的版本。这里指的是文件没有经过任何提交,仅仅只是保存。一种补救的方法就是修改错误的版本,push一个新的上去就行。查看本次提交之前的版本,并记住想要回退的版本的id。指令将暂存区的文件回退到修改之前的状态。在Git中,一份代码可能处于不同的提交阶段。指令将暂存区的文件回退到修改之前的状态。一份新修改(或者创建的)文件处于 –

2022-12-28 15:47:33 5935 1

原创 论文写作:word连续交叉引用

在写作得时候,使用word的 “交叉引用”功能可以形成超链接格式的标号。但是交叉引用每次只能选择一篇论文,在连续选择多篇论文的时候,就是 “[1][2][3]” 而不是 “[1-3]” 这样的格式。

2022-11-18 16:02:12 1463

原创 虚拟机的三种可选模式:桥接模式、NAT模式、主机模式浅析

在配置虚拟机的时候,往往有三种可供选择的网络模式:桥接模式、NAT模式、主机模式浅析。查阅了有关的资料,在下面对这三种模式做一下区分。

2022-11-15 20:39:19 2848 1

原创 Matlab 统计不同元素个数

假设我手里有个数据集,每个类别的个数是不一样的。现在我想把数据整理成每个类别的个数都是相等的,应该怎么处理?

2022-10-01 21:20:20 5738

原创 TCP和UDP在socket编程上的差异(总结)

UDP不需要监听(listen函数)UDP不需要创建连接(accept函数)UDP获取接收方的信息(IP、端口)是在recvfrom函数,而TCP是在accept函数。UDP不需要创建连接(connect函数)收发消息使用的函数不同。

2022-09-28 08:56:44 1406

原创 variable ‘XXX cannot be implicitly captured in a lambda with no capture-default specified

原因是函数也是一个对象,需要进行捕获。上面的匿名函数isValid没有捕获另一个匿名函数isAlpha,因此报错,只需要在isValid的捕获列表中该为[=] 或者 [&]即可。今天在日常刷题的时候,使用了lambda函数。

2022-09-25 13:48:14 4409

原创 C++ STL迭代器失效问题

在STL里面的容器往往封装了迭代器。迭代器能让人很方便的拿到容器里面的元素进行操作。然而,在不同结构的容器中,删除一个迭代器可能会引发迭代器失效的问题。下面针对不同的容器类型做一下总结。

2022-09-15 22:06:15 1897

原创 未确定数组个数、大小的ACM模式输入输出(C++)

最近在面试笔试的时候,极大多数笔试都是输入输出的模式。对于确定了数组或者字符串个数的输入,读取比较简单,在这里不再赘述。

2022-09-12 23:48:33 1152

原创 设计模式:观察者模式(C++实现)

观察者模式模式又称为发布-订阅模式。订阅消息的一方称为观察者,而发布消息的一般称为主题类。观察者在一开始的时候会向主题类注册自己感兴趣的事件,当主题类发布了一个特定事件的时候,观察者就会收到主题类的通知,从而完成状态变化。

2022-09-12 22:16:31 461

原创 动态开点线段树(C++实现)

所谓懒标记,就是把本区间一些增加的量给保留下来,等到需要用到左右结点的时候,才把这些增加的量分给左右孩子,让它们去更新自己区间的值。首先,当需改修改的区间包含了当前的区间,那么我们更新了当前结点的值,然后马上返回了。很明显,这道题就是在制定某个形成区间前,查一下这个区间是不是有安排了(有的话这个区间的和大于1,没有的话等于0,每次制定一个行程区间都是为这个区间的所有元素+1)。每个结点都是维护了一个区间的性质(在上图里面表示一个区间的和),区间的最小长度为1,也就是这个区间有且仅有一个元素。

2022-09-10 21:02:50 1141 2

原创 shared_ptr的线程安全性探讨

在 一文详解C++11的三种智能指针中,我们详细探讨了C++11中提供的三种智能指针的应用场景以及shared_ptr的实现。今天需要探讨的是:shared_ptr的安全性。先上结论:不安全,需要加锁。

2022-09-09 18:46:35 771

原创 设计模式:饿汉式和懒汉式单例模式(C++实现)以及日志系统的实现

在一个项目的日志系统里面,我们常常会发现日志模块的实现是使用单例模式。单例模式的特点和它的名字一样,就是一个类能且只能实例化出一个唯一的对象。那么这样做有什么好处呢?

2022-09-09 16:03:30 1226 2

原创 epoll比select和poll究竟高效在哪儿(剖析及实现)

来说,它在文件描述符使用epoll_ctl加入事件表的时候,就设置了改文件描述符在发生就绪事件时的回调函数。所以,在用户使用的时候,可以直接拿到就绪的文件描述符和对应发生的事件,而不需要轮询,因此效率比较高。这个事件表是使用红黑树这个数据结构进行管理的,因此,有了这个红黑树,就可以不用像select或者poll一样,把一个数组从用户态拷贝到内核态,而是使用epoll_ctl进行管理就行了。的时候,不需要重复传入用户监听的文件描述符,省去了大量的文件描述符的复制开销。然后在事件实际发生的时候,只会修改。

2022-09-08 15:31:03 631

原创 LRU算法学习笔记:实现以及应用

所谓LRU(Least Recently Used)就是最近最少使用算法。其核心的思想就是根据每个节点的最后一次访问事件来对每个结点进行排序。最近一次使用的排在队头,依次类推。

2022-09-07 22:24:40 661

原创 解决:Linux下C++段错误不产生core文件

在已经使用打开了core文件的基础上,运行程序产生了段错误。使用ls命令查看当前目录下的文件,还是没看见任何和.core相关的文件。如下:ulimit -cunlimited发现结果被|

2022-09-07 14:09:27 5098 3

原创 Linux下排除死锁详细教程(基于C++11、GDB)

在实际编写项目的过程中,经常涉及到多线程。多线程的程序编程很大概率会涉及到线程安全的问题,因此往往使用互斥锁来保证线程安全。然而,互斥锁的使用却经常会导致另外一个问题:死锁。所谓死锁,通俗的讲就是有两个共享资源,一个在你手上,一个在我手上。我等着你用完把另一个给我,你等我用完给你,这样相互等待就形成了死锁。所以,在这里,基于Linux的环境,使用C++11提供的多线程编程来模拟死锁,并尝试从“不知情”的角度,使用进行死锁的排查。

2022-09-05 14:15:26 3756 1

原创 设计模式:装饰器模式(C++实现)

首先先上结论:装饰器模式的设计场景是为已有的类增加新的功能。有人可能会觉得有些奇怪:增加新的功能可以通过继承的方式进行实现。例如,我通过public继承把父类的东西全部继承过来,接口也全部继承过来,然后在子类的基础上增加新的接口不就行了?其实理论上确实是可以的,但是这种方式通过继承+增加功能(接口)的方式在某些情况下可能会存在冗余,而装饰器的设计模式可以减少这种冗余。例如,假设现在有两个个汽车的厂家:BWM、Benz。

2022-09-04 19:44:09 397

原创 设计模式:适配器模式(C++实现)

那么这时候就需要一个转换器(适配器)来作为中间的桥梁,来将HDMI的信号转换为老的信号,从而被显示器接收工作。比如我们电脑连接投影仪(或者显示屏)的时候,老一点的电脑接口经常是VGA的,而新一点的可以是HDMI的或者TypeC的。这里的 Computer01 是第一代的电脑,比较老,只能输出VGA的信号,而投影仪只能接受一个VGA的老对象,这样工作是没问题的。这个老的一般指的是“接口传入的对象是老的”。VGAToHDMIAdaptor虽然是一个“旧对象”,但是它的构造函数可以接受一个新的对象。

2022-09-04 16:12:08 515

原创 web服务器改进:迷你线程池+CAS自旋锁(Demo)

最近有学习一些关于C++11从语法层面上提供的多线程编程。本来考虑使用C++11的互斥锁来实现线程间的互斥,而C++提供的互斥锁是比较简单的,和Linux的使用没有太大区别。另一方面,在面试的时候,会涉及一些无锁的互斥手法。在webserver项目中,请求队列的任务在出队和入队上都需要互斥锁。而互斥锁比较重,需要执行系统调用。而系统调用又需要陷入内核态,调度完切换回用户态又需要时间,因此效率较低。这时候,采用CAS+自旋锁的手法效率会比较高。因此,下面的例子借鉴muduo网络库实现一个迷你版的线程池。...

2022-08-30 21:06:00 345

原创 有向图、无向图相关数据结构

最近面试的公司是做地图业务相关的,可能在路径规划、路径搜索方面会涉及图相关的知识,因此趁着这个机会把图相关的知识补充整理一下。如果对图进行大分类的话,主要可以分为有向图和无向图。所谓有向,指的就是从A点到点B这条路径是成立的,而从点B到点A这条路径不一定成立。而无向图的话,从A可以到B的话,意味着也可以从B到A。邻接矩阵、邻接表、十字链表、邻接多重表。1. 邻接矩阵来表示图的话比较直观。可以根据每一行来判断每一个顶点出度对应的终点在哪,根据每一列可以判断每一个顶点的入度的起点是谁。

2022-08-20 16:20:18 1824

原创 C++ 优先级队列(运用绑定器实现大小根堆)

但是,对于大根堆来说,每个节点的父节点是需要大于它的孩子节点的。刚插入的、放在叶子节点中的这个节点可能比它的夫节点还要大,因此需要进行。对于出堆,首先需要记录数组的第一个元素(相当于堆顶元素)的值,然后用最后一个值覆盖第一个元素。对于入堆,一开始其实把入堆的元素放到数组的最后面。放在最后的这个元素在二叉树里面相当于就在叶子结点中。这时新的堆顶元素不一定能符合父节点大于两个孩子节点的条件,因此需要进行。中,其实是使用大小根堆实现的(默认是大根堆)。绑定了一根函数对象来自定义的实现大小根堆。...

2022-08-18 08:58:55 477

原创 海量数据TopK问题

可以使用大根堆来实现。迭代数据,在迭代过程中,堆里面维护了目前为止的遇到的前K个重复次数最小的元素。迭代完成时,取出即可。大根堆的调整为O(logk)的时间复杂度,k为大根堆的层数。因此是常量时间,可以去掉。只剩下O(n)的遍历元素的时间。从海量数据中找出出现次数最少的前K个值,且算法复杂度为O(n)。...

2022-07-23 15:55:34 263

原创 海量数据查重问题一网打尽:哈希表、位图、布隆过滤器

在面试的时候可能经常会问道海量数据的查重问题,大概就是在有限的内存空间中进行数据的查重。在实际场景中,哈希表、位图、布隆过滤器都能发挥自己作用。1.哈希表使用的内存是最多的。在使用哈希的表过程中,需要一大块连续的内存空间。而且内存空间一般是存储元素的两倍。2.位图在某些情况下大大压缩了哈希表的使用空间。在使用的过程中,位图其实也需要开辟一段连续的内存空间,但是因为其数据底层用一个位来表示一个key的状态,极致的压榨了空间的利用率。但是一个位往往只能表示”是“、”否“这两个状态。...

2022-07-22 23:29:47 475

原创 web服务器设计(二):线程池的设计

在此,设计的线程池主要创建了多个子线程来从请求队列中拿出请求并执行。同时,还需要提供插入请求的接口,用于主线程在完成读写I/O后将请求插入队列中。同时,线程池的设计还需要考虑线程安全。在不同的线程操作队列的时候,需要对队列进行加锁。没有请求在队列的时候,为了降低CPU的利用,我们利用信号量在队列中没有请求时挂起线程,在插入一个请求后唤醒。......

2022-07-16 16:36:04 379

原创 网络编程:阻塞、非阻塞、同步、异步的区分

在网络编程的过程中,我们操作一次I/O的时候,其实通常都会经历两个不同1.数据的准备阶段2.数据的读写阶段通常,在数据的准备阶段我们会选择当前的I/O操作是阻塞的还是非阻塞的;而在数据的读写阶段,我们会选择当前的当前的I/O操作是同步的还是异步的。这就是四者在全局上的一个综合关系。...

2022-07-14 20:16:42 368

原创 一文详解C++11的三种智能指针

在C++11中出现三种智能指针,分别是unique_ptr、shared_ptr、weak_ptr。这三种智能指针分别有各自的应用场景,同时这些应用场景是有相互联系的。和名字一样,unique_ptr的特点就是“独占”的意思,多个unique_ptr无法指向同一对象。相比于裸指针,unique_ptr的最大优势当然是超出作用域时会自动释放资源。其实unique_ptr解决的并不只是资源自动释放的问题。在C++11之前还有这两种类型的指针,unique_ptr在资源自动释放的同时也假设有下面的代码:在上面的

2022-07-14 16:24:36 4051 1

原创 一致性哈希

这里的哈希结果不变很好理解。通常如果我们的哈希函数采用了除留余数法,比如现在我有三个数100、54、2。如果我想一个哈希函数来把这三个数放进一个连续的数组里面,那么我只要对这些数都模上3即可。所以:那么,多次结果不变有什么用?鲁棒性是什么意思?所以,有没有可能第三台服务器崩了只影响第三台服务器的原本客户,而不影响其他服务器的客户呢?...

2022-07-12 22:51:35 587

原创 C++ 手撕红黑树(二):删除操作

前情概述:C++ 手撕红黑树(一):节点的插入当需要删除的节点颜色是黑色时,最基本的情况如下所示:情况1,兄弟是黑色的,而且有一个红色的右孩子:情况2,兄弟是黑色的,但是右孩子是黑色的,而左孩子是红色的:情况三:兄弟的孩子都是黑色的总结一下:3. 整棵红黑树的实现5.测试结果...

2022-07-11 21:47:29 610 3

原创 C++ 手撕红黑树(一):插入操作

红黑树的出现主要是用来解决AVL树旋转次数过多的问题。AVL树在插入节点或者删除节点的过程中(每层递归完回溯时)都需要检查左子树或者右子树之间的高度差是否小于等于1,如果不平衡(大于1)的话需要旋转或者平衡操作来维持平衡,因此在数据量比较大的时候可能旋转了很多次(接近logn次),效率比较差。而红黑树在插入和删除的时候,最多做两次旋转操作。因此旋转次数比较少。然而,值得注意的是,红黑树是一颗BST树但并不是一颗平衡的树。......

2022-07-11 11:10:26 588 3

原创 VScode配置GItbash为终端

VScode配置Gitbash为终端

2022-07-09 08:38:35 4200

原创 分布式项目学习笔记(二):本地服务发布成RPC服务

在这个过程中,主要需要做两件事:首先需要主机B来创建一个 文件来注册本地业务的RPC方法:这里最关键的就是最后一段代码,它注册一个RPC方法:。在注册了方法之后。主机B需要具体实现接口里面的内容:这里的具体实现是主机B继承了来实现接口里面的内容。第一个其实就是本地的方法,第二个带有很多参数调用了本地的来真正执行本地的操作。里面的参数其实就是RPC框架在网络中接收到的参数。......

2022-07-05 15:21:45 359

原创 Leetcode44: 通配符匹配

这种和前一个状态有关的题目当然是求解了。问题是:1. 遇见 “*” 怎么处理?2. 遇见 “?” 怎么处理?

2022-07-05 09:48:30 139

原创 分布式项目学习笔记(一):protobuf 的安装以及使用

由于分布式需要在不同的主机之间进行通信,因此需要对信息进行打包。protobuf 正是提供了这两个过程的一个库。三、功能的简单测试我们可以编写简单的文件来测试protobuf 的功能:2. 对test.proto进行编译其中,protoc 是编译命令,test.proto是文件名,./ 是指定了当前的路径编译之后会增加两个文件 test.pb.cc 和 test.pb.h(忽略main.cc 和 a.out):3.1 编译3.2 运行3.3 输出结果完成收工!!!...

2022-07-03 15:59:45 478

原创 C++ AVL树手撕代码实现

AVL树是为了解决BST(二叉搜索树)树在一些情况下树的形状退化成线性链表而诞生的一种树。它有着BST树的特点(中序遍历是顺序的),但是有新的特点:因此,AVL树是高度平衡的二叉搜索树。为了保持平衡,在四种情况下,树的结构要进行变形。这四种情况分别为:在发生上面四种情况时,则需要变形操作。变形的操作分为左旋和右旋。下面是四种情况的示意图:2.2 右旋2.3 左平衡(左旋+右旋)2.4 右平衡二、AVL树的实现AVL树的重点在于操作。3.删除操作在找到需要删除的节点后,可以分为三种情况

2022-07-01 20:45:54 421

原创 C++ 手写智能指针 shared_ptr

C++智能指针简单实现

2022-06-30 15:55:22 2083 1

原创 new、express new、operator new、placement new 之间的千丝万缕

第一,编译器帮我们调用了operator new 来 申请一块干净的内存(未经过初始化)。第二,编译器帮我们把得到那块内存用static_cast函数进行类型转换成对应的类型。(C++的四种cast动作详解)第三,编译器帮我们调用了构造函数,在分配的内存中进行对象的构造。 在步骤一中 operator new 接收了一个参数,指明了“我想要多少字节的内存”。而对于后续的步骤二、三来说,从步骤一中得到的内存究竟是从哪儿来的其实它们并不关心,毕竟它们的职责只是构造对象而已。因此,我们就能对某些版本的op

2022-06-28 18:16:43 401

原创 Linux下Makefile操作

如:上面的例子一共有两条规则,第二条规则是生成add.o文件。但是,第一条规则生成app文件的过程中,和add.o并没有任何关系,因此第二条规则是不会执行的。如图:执行make命令之后:可以看见,make 命令之后并没有执行第二条规则。而且用ls命令查看文件发现没有add.o文件生成。写Makefile文件的过程中,可以通过定义变量、使用函数的办法来少打一些命令和文件的名称。比如,在上面的Makefile 文件中,很多.c文件都是手打的,因此,我们可以通过函数的方式来获取这些.c文件的文件名

2022-06-26 18:38:29 5303

原创 new和 delete 细细碎记录

如图所示,假设我们需要对类Complex申请动态内存,在调试模式下和在非调试模式的如左1,左2所示,其中:左3和左4为String对象申请分配的内存,String对象在设计时往往带有一根char* 的指针指向自己的字符串,因此分配一个String对象只需要4个字节。后面分析同上。与分配单个对象相比,在VC下多了四个字节来存储内存中有几个对象(白色块)。由于这块内存记录了里面究竟有多少个对象的空间,delete[] 时如果调用了delete其实不会造成这块内存的泄露。而因为delete和delete[]相比,

2022-06-24 15:51:03 152

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除