自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(684)
  • 资源 (1)
  • 收藏
  • 关注

原创 C++中可变参数宏

可变参数宏(Macro With Variable Number of Arguments or Variadic Macro) 是指我们可以像定义能够接受不同数量参数的普通C++函数一样,定义一个能够接受不同数量参数宏。

2023-04-27 19:56:01 1259 1

原创 IPC和RPC

这个概念泛指进程之间任何形式的通信行为,是个可以拿来到处套的术语。它不仅包括各种形式的消息传递,还可以指共享资源,以及同步对象[mutex 或者其他类似的东西,即确保安全的并发访问共享资源(也就是防止两个或两个以上的对象同事对同一个数据成员进行修改,从而导致数据被破坏,或者竞争条件下同事读/写数据而导致错误的情况发生)]的东西。

2022-09-16 11:41:20 527

原创 IO密集型线程和CPU密集型线程

CPU密集任务只有在真正的多核CPU上才可能得到加速,而在单核CPU上,无论你开几个模拟的多线程该任务都不可能得到加速,因为CPU总的运算能力就只有这么多。CPU密集型也叫计算密集型,指的是系统的硬盘、内存性能相对CPU要好很多,此时,系统运作CPU读写IO(硬盘/内存)时,IO可以在很短的时间内完成,而CPU还有许多运算要处理,因此,CPU负载很高。IO密集型指的是系统的CPU性能相对硬盘、内存要好很多,此时,系统运作,大部分的状况是CPU在等IO (硬盘/内存) 的读写操作,因此,CPU负载并不高。

2022-09-06 21:56:47 3041

原创 C++三种函数传参方式

传的是地址,值传递特点是被调函数对形式参数的任何操作都是作为局部变量来进行的,不会影响到主调函数的实参的值,但是因为传的是地址,因此其实也在改变了这个地址上的变量。形参和实参实际是相互独立的。是把实参的地址传给形参,因为形参和实参对象指向的地址是一样的,所以因此形参指向的对象就是实参的对象。,就是两个变量直接指向同一个对象,形参相当于是实参的另外一个别名,因此形参改变,实参也改变。值传递是最常见的一种方式,就是典型的把实参复制一份传递给形参,函数无法改变实参的值。

2022-09-06 21:20:41 992

原创 前置++和后置++的区别

前置++的返回类型是Age&,后置++的返回类型const Age。这意味着,前置++返回的是左值,后置++返回的是右值。前置++与后置++的操作符重载函数,函数原型必须不同,否则就违反了重载函数必须拥有不同的函数原型的语法规定。前置++的效率更高,理由是:后置++会生成临时对象,会造成一次构造函数和一次析构函数的额外开销。该类重载了前置++和后置++两个操作符,以实现对年龄的自增。前置++没有形参,而后置++有一个int形参,这是为了绕过语法的限制。左值和右值,决定了前置++和后置++的用法。

2022-09-05 21:48:47 852

原创 空悬指针、野指针、NULL、nullptr

为了解决这种二义性,C++11标准引入了关键字nullptr作为空指针常量。​nullptr隐式转换为指针类型,而无法隐式转换为整形,编译器会找到形参为指针的函数版本,消除了NULL带来的二义性。,这是因为在​C++里面,NULL是这样定义的:​。...

2022-08-31 21:04:10 576

原创 C++ =default

在c++中如果我们自行定义了一个构造函数,那么编译器就不会再次生成默认构造函数,我们先看如下的代码我们定义一个类,这个类没有定义构造函数,此时在下面一段代码依然可以正常使用,我们加上一个自定义构造函数:此时编译器会报错,原因很简单,我们自定义了一个构造函数,以前的默认构造函数没了,我们要用如下的方式调用:如果我们还要使用无参构造函数得在定义时自己写个好了此时不报错了,但是这样写代码执行效率没有编译器生成的自定义函数的效率高,为了解决这个问题,C++11 标准引入了一个新特性:default 函数。程

2022-08-30 21:35:23 5336

原创 为什么不建议使用select *

由于辅助索引的数据比聚集索引少很多,很多情况下,通过辅助索引进行覆盖索引(通过索引就能获取用户需要的所有列),都不需要读磁盘,直接从内存取,而聚集索引很可能数据在磁盘(外存)中(取决于buffer pool的大小和命中率),这种情况下,一个是内存读,一个是磁盘读,速度差异就很显著了,几乎是数量级的差异。如果用户使用select *,获取了不需要的数据,则首先通过辅助索引过滤数据,然后再通过聚集索引获取所有的列,这就多了一次b+树查询,速度必然会慢很多。...

2022-08-28 22:16:20 577

原创 C++11 auto和decltype

∶。

2022-08-28 20:44:29 570

原创 define和typedef有什么区别

define是C语言中定义的语法,是预处理指令,在预处理时进行简单而机械的字符串替换,不作类型检查。typedef是关键字,它在自己的作用域内给一个已经存在的类型一个别名,在编译时处理,有类型检查功能。#define不只是可以为类型取别名,还可以定义常量、变量、编译开关等。typedef用来定义类型的别名,起到类型易于记忆的功能。...

2022-08-28 15:36:35 380

原创 多线程有哪些锁

互斥锁是一种「独占锁」,比如当线程 A 加锁成功后,此时互斥锁已经被线程 A 独占了,只要线程 A 没有释放手中的锁,线程 B 加锁就会失败,于是就会释放 CPU 让给其他线程,既然线程 B 释放掉了 CPU,自然线程 B 加锁的代码就会被阻塞。自旋锁开销少,在多核系统下一般不会主动产生线程切换,但如果被锁住的代码执行时间过长,自旋的线程会长时间占用 CPU 资源,所以自旋的时间和被锁住的代码执行的时间是成「正比」的关系,我们需要清楚的知道这一点。互斥锁虽然简化了使用锁的难度,但是存在一定的性能开销,...

2022-08-26 11:16:15 1893

原创 C++ STL的空间配置器

一级配置器的实现思想实际就是对c下的malloc,relloc,free进行了封装,并且在其中加入了c++的异常。我们要了解对于当内存不足调用失败后,内存不足处理是用户需要解决的问题,STL不处理,只是在你没有内存不足处理方法或有但是调用失败后抛出异常。二级配置器是通过内存池和空闲链表配合起来的一个特别精巧的思想。空闲链表的每个节点分别维护以8的倍数的各内存大小(8,16,32…128字节)。首先,用户申请内存小于128个字节,进入二级配置器程序,...

2022-08-25 16:29:13 600

原创 char *s1 和 char s2[] 的区别

【代码】char *s1 和 char s2[] 的区别。

2022-08-23 10:49:07 494

原创 C++ union联合体

因为共用体将一个char类型的mark、一个long类型的num变量和一个float类型的score变量存放在同一个地址开始的内存单元中,而char类型和long类型所占的内存字节数是不一样的,但是在union中都是从同一个地址存放的,也就是使用的覆盖技术,这三个变量互相覆盖,而这种使几个不同的变量共占同一段内存的结构,称为“共用体”类型的结构。由于a的存储区有好几种类型,分别占不同长度的存储区,仅写共用体变量名a,这样使编译器无法确定究竟输出的哪一个成员的值。

2022-08-22 23:11:53 760

原创 从操作系统的层面思考一个程序运行的全过程

1

2022-08-19 18:26:09 598

原创 用户级线程和内核级线程

据操作系统内核是否对线程可感知,可以把线程分为内核线程和用户线程。用户级线程由应用程序所支持的线程实现, 内核意识不到用户级线程的实现。内核级线程又称为内核支持的线程。

2022-08-17 21:28:40 3522

原创 C++ sizeof

length()是因为沿用C语言的习惯而保留下来的,string类最初只有length(),引入STL之后,为了兼容又加入了size(),它是作为STL容器的属性存在的,便于符合STL的接口规则,以便用于STL的算法。string类的size()/length()方法返回的是字节数,不管是否有汉字。可以看到,sizeof(a)是20个字节,sizeof(b)是4个字节,也就是说sizeof(b)只是求出了指针b的大小。,参数可以是数组、指针、类型、对象、函数等。(1)size()用于取对象大小。......

2022-08-17 20:22:16 345

原创 为什么条件变量的wait函数需要传入一锁作为参数

要注意到,#1和#2两步已经不是原子操作了,那么就有可能有如此情景:在当前线程(A)执行完#1行代码后到执行#2代码前的时间间隔里,另一线程(B),获取到了锁,修改了条件使其满足,然后发送了信号condA。而此时线程A还未被加入到condA的等待队列中,造成线程A错过了通知一直阻塞,直至下一次通知,如果没有下一次通知,那么A将永远等待下去,比如B也需要A的相关条件变量通知才能再次发出condA的通知。此为,为保证“解锁”和“加入等待队列”两操作的原子性,条件变量的wait函数需要传入一锁作为参数。.....

2022-08-16 21:01:28 514

原创 构造函数和析构函数能抛出异常吗?

但是当无法保证析构函数中不发生异常时,该怎么办呢?析构函数不能、也不应该抛出异常。构造函数可以抛出异常,但是不建议这么做。

2022-08-16 20:29:33 1865

原创 Reactor和Proactor

另外,「单 Reactor」的模式还有个问题,因为一个 Reactor 对象承担所有事件的监听和响应,而且只在主线程中运行,在面对瞬间高并发的场景时,容易成为性能的瓶颈的地方。单 Reactor 单进程的方案因为全部工作都在同一个进程内完成,所以实现起来比较简单,不需要考虑进程间通信,也不用担心多进程竞争。所以,单 Reactor 单进程的方案不适用计算机密集型的场景,只适用于业务处理非常快速的场景。...

2022-08-16 11:16:34 399

原创 TCP连接过程中如果拔掉网线会发生什么?

由于拔掉网线并不会改变客户端的 TCP 连接状态,并且还是处于 ESTABLISHED 状态,所以这时客户端是可以正常接收服务端发来的数据报文的,然后客户端就会回 ACK 响应报文。服务端超时重传报文的次数达到一定阈值后,内核就会判定出该 TCP 有问题,然后通过 Socket 接口告诉应用程序该 TCP 连接出问题了,于是服务端的 TCP 连接就会断开。此时,客户端和服务端的 TCP 连接都已经断开了。在客户端拔掉网线后,服务端向客户端发送的数据报文会得不到任何的响应,在等待一定时长后,......

2022-08-10 18:09:50 1868

原创 C和C++的区别

因此,C与C++的最大区别在于,它们用于解决问题的思想方法不一样。而在C++中的C,相对于原来的C还有所加强,引入了重载、内联函数、异常处理等。在C++中,不仅需要考虑数据封装,还需要考虑对象的粒度的选择、对象接口的设计和继承、组合与继承的使用等问题。C程序的设计首要考虑的是如何通过一个过程,对输入进行运算处理,得到输出。C++是面向对象的,C++程序的设计首要考虑的是如何构造一个对象模型,让这个模型能够配合对应的问题,这样就可以通过获取对象的状态信息得到输出或实现过程控制。...

2022-08-09 20:06:56 1490

原创 ASCII、Unicode和UTF-8

标准ASCII码也叫基础ASCII码,使用7位二进制数(剩下的1位二进制为0)来表示所有的大写和小写字母、数字0到9、标点符号以及在美式英语中使用的特殊控制字符。ASCII码只是用了7位二进制数,用一个字节表示时,它第一位总是为0。如果只表示英文,一个字节是够用的,但要表示世界上所有的文字,必须使用多个字节才行。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。UTF-8就是在互联网上使用最广的一种unicode的实现方式。...

2022-08-08 10:47:16 363

原创 为什么数据需要序列化

当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,发送方需把这个对象转换为字节序列,才能在网络上传送;接收方则需把字节序列再恢复为对象。把对象转换为字节序列的过程称为对象的序列化。把字节序列恢复为对象的过程称为对象的反序列化。因此,序列化的目的就是为了跨进程传递格式化数据。...

2022-07-29 15:55:22 416

原创 ping命令

当A设备pingB设备时候,会同时发出arp和icmp协议。arp协议用于根据目的ip获取默认网关的mac地址,icmp协议用于实现ping的功能。MAC地址在两个设备间通信时变化,传送时DestMac和SourceMac会一直不停变化,但是ip地址始终不变。...

2022-07-18 20:25:05 413

原创 MySQL中select语句的执行过程

MySQL的架构如下图所示一个select语句的执行过程如下所示。

2022-07-17 21:40:05 1459

原创 数据链路层是如何传递数据的

数据链路层的主要作用就是加强物理层传输原始比特流的功能。其负责将物理层提供的可能出错的物理连接,改造成逻辑上无差错的数据链路,使之对网络层表现为一条无差错的链路。封装成帧、透明传输、差错控制。............

2022-07-15 11:10:51 1371

原创 C++ STL sort函数的底层实现

sort函数的底层用到的是内省式排序以及插入排序,内省排序首先从快速排序开始,当递归深度超过一定深度(深度为排序元素数量的对数值)后转为堆排序。先来回顾一下以上提到的3中排序方法:其中先讲下快排和堆排,快排的平均复杂度为nlogn,但是它的复杂度是根据基准值来决定的,基准值选择的不好,最坏的复杂度会达到n2,而堆排序的复杂度是一定的为n*logn,那为什么不直接使用堆排序呢,是因为在将堆顶值与最后一个结点值交换并移除最后一个值后,在重新建堆的过程中,交换到堆顶的值显然比每个结点要小,但还是要经过对比判断,这

2022-07-10 21:01:35 1763

原创 C++11多线程相关类

C++11 新标准中引入了五个头文件来支持多线程编程,他们分别是 ,,,和。mutexcondition_variable创建ThreadA和ThreadB两个线程,线程分别运行的是A和B两个函数,线程ThreadB通过cv.wait()来阻塞等待,线程ThreadA通过修改全局标志位和cv.notify_one()来唤醒ThreadB继续往下运行。...

2022-06-18 15:53:15 153 1

原创 生产者消费者模式

生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了共享固定大小缓冲区的两个线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题需要注意的几点:实现生产者消费者模式的C++代码如下:......

2022-06-16 22:33:41 108

原创 MySQL的两阶段提交(数据一致性)

MySQL的两阶段提交两阶段提交过程为什么要写redo log,不写redo log的话,根本就不会出现“两阶段提交”的麻烦事啊?为什么要写两次redo log,写一次不行吗?在两阶段提交的情况下,是怎么实现崩溃恢复的呢?在讲解两阶段提交之前,需要对MySQL中的binlog、redo log和undo log有一定的了解。两者的适用场景不同,binlog适用于维护集群内数据的一致性,redo log用于崩溃恢复,undo log相对于前面两种日志更好理解些,就是为了回滚事务用的。两阶段提交过程Inn

2022-05-23 21:27:09 6987 5

原创 C++ explicit关键字用法详解

explicit关键字隐式类类型转换explicit关键字隐式类类型转换在C++语言中,类中的构造函数如果只含有一个参数,默认情况下存在一种隐式转换,即定义了转换为此类类型的隐式转换机制。然而,这种机制并非总是合理的,甚至容易产生错误,因此,新标准增加了explicit关键字,用来限制隐式转换。下面的示例是隐式转换的机制:class Test {public: Test(); // 空构造函数 Test(double a); // 含一个参数的构造函数 Test(int

2022-05-19 21:17:10 192

原创 C++空类中有哪些默认的函数

这里写目录标题C++的空类会有6个默认的函数。即默认构造函数、默认拷贝构造函数、默认析构函数、默认赋值运算符,这四个是我们通常知道的。但是除了这四个,还有两个,那就是取址运算符和const 取址运算符,即总共有六个函数。一个示例如下:class Empty{public: Empty(); // 缺省构造函数 Empty( const Empty& ); // 拷贝构造函数 ~Empty(); // 析构函数 Empty& operator=( const Empty&amp

2022-05-18 20:20:57 2869

原创 MySQL如何处理死锁

MySQL有两种死锁处理方式:等待,直到超时(innodb_lock_wait_timeout=50s设置锁等待的时间,前提已经检测到锁的产生)。发起死锁检测,主动回滚一条事务,让其他事务继续执行,回滚代价最小的那一个事务(innodb_deadlock_detect=on)。由于性能原因,一般都是使用死锁检测来进行处理死锁。死锁检测的原理是构建一个以事务为顶点、锁为边的有向图,判断有向图是否存在环,存在即有死锁。检测到死锁之后,选择插入、更新或者删除的行数最少的事务回滚,基于 INFORMATI

2022-05-18 19:08:00 6381

原创 惊群效应及其解决方法

这里写目录标题惊群效应的概念惊群效应的危害惊群效应的解决方法在accept之前加锁SO_REUSEPORT惊群效应的概念惊群现象就是多进程(多线程)在同时阻塞等待同一个事件的时候(休眠状态),如果等待的这个事件发生,那么他就会唤醒等待的所有进程(或者线程),但是最终却只可能有一个进程(线程)获得这个时间的“控制权”,对该事件进行处理,而其他进程(线程)获取“控制权”失败,只能重新进入休眠状态,这种现象和性能浪费就叫做惊群。惊群效应的危害系统对用户进程/线程频繁地做无效的调度,上下文切换系统性能大打

2022-05-17 20:39:03 2081

原创 C++ strcpy,memcpy,memset,strcmp,memcmp

这里写目录标题strcpymemcpymemset的用法strcpy原型:extern char *strcpy(char *dest,char *src);功能:把src所指由’\0’结束的字符串复制到dest所指的数组中。 src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。返回指向dest的指针。#include<string.h>#include<iostream.h>void main(){char a[20],c[]="i

2022-05-09 21:51:10 787

原创 Linux中进程虚拟内存的布局

操作系统虚拟内存的布局Linux虚拟内存空间布局总览预留段(.reserve)代码段(.text)数据段(.data)数据段(.bss)堆(.heap)栈(.stack)共享库(libc.so)Linux虚拟内存空间布局总览预留段(.reserve)一共占用128M,属于预留空间,进程是禁止访问的代码段(.text)可执行文件加载到内存中的只有数据和指令之分,而指令被存放在.text段中,一般是共享的,编译时确定,只读,不允许修改数据段(.data)存放在编译阶段(而非运行时)就能确定的数据

2022-05-04 21:41:02 493

原创 哈希表hash的扩容

哈希表hash的扩容字典dict的结构哈希表hash的扩容(rehash)渐进式哈希字典dict的结构了解hash的扩容之前,需要先了解hash的底层实现:dict。dict所使用的哈希表由 dict.h/dictht 结构定义:typedef struct dictht { // 哈希表数组 dictEntry **table; // 哈希表大小 unsigned long size; // 哈希表大小掩码,用于计算索引值 // 总是等于 si

2022-05-01 21:26:05 3621 1

原创 C++内存分配的几种策略

内存分配的几种策略静态的栈式的堆式的区别静态的静态的存储区:内存在程序编译的时候就已经分配好,这块的内存在程序整个运行期间都一直存在。它主要存放静态数据、全局的static数据和一些常量。栈式的在执行函数(方法)时,函数一些内部变量的存储都可以放在栈上面创建,函数执行结束的时候这些存储单元就会自动被释放掉。栈内存包括分配的运算速度很快,因为内置在处理器的里面的。当然容量有限。堆式的也叫做动态内存分配。有时候可以用malloc或者new来申请分配一个内存。在C/C++可能需要自己负责释放(java

2022-05-01 20:29:03 1858

原创 Linux中父进程与子进程的内存关系

fork()会产生一个和父进程完全相同的子进程,出于效率考虑,linux中引入了写时复制技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。那么一开始子进程的物理空间没有代码,怎么去取指令执行exec系统调用呢?原来在fork之后exec之前两个进程用的是相同的物理空间(内存区),子进程的代码段、数据段、堆栈都是指向父进程的物理空间,也就是说,两者的虚拟空间不同,但其对应的物理空间是同一个。当父子进程中有更改相应段的行为发生时,再为子进程相应的段分配物理空间,如果不调用e

2022-04-25 20:57:01 1237

作业车间调度C++,GA实现

作业车间调度C++参考代码,可以用来参考。遗传算法是运用最广泛的一个算法,在调度问题中的使用也十分频繁,因此采用此算法来解决作业车间调度问题,希望给大家带来帮助。

2020-01-27

空空如也

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

TA关注的人

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