自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 socket server服务器开发常见的并发模型

只要是做服务器开发,那么常见的模型是通用的,C/C++/go等等都是通用的,因为这是一种设计思想。其中模型五是实际开发中主流的,而模型六还存在一些弊端需要改进。模型一:单线程accept(无IO复用)模型分析:①主线程执行阻塞accept,每次客户端connect请求连接过来,主线程中的accept响应并建立连接②创建连接成功之后,得到新的套接字文件描述符cfd(用于与客户端通信),然后在主线程串行处理套接字读写,并处理业务。③在②的处理业务时,如果有新的客户端发送请求连接,会被阻塞,服务器

2021-11-02 22:28:18 1478

原创 C++工厂模式个人总结

工厂模式,结合智能指针和类模板

2023-02-27 16:59:59 215

原创 C++ 手写String类

面试准备,记录一下

2022-09-04 16:46:51 645 4

原创 手撕shared_ptr智能指针

面试中遇到的,自己做个总结

2022-09-01 16:00:02 389

原创 费曼学习法(符号表)

符号表面试题

2022-07-27 22:27:14 368

原创 费曼学习法(Redis总结)

redis重点总结

2022-07-21 00:12:34 141

原创 防御塔攻击小兵,C++观察者模式

C++观察者

2022-06-26 15:08:19 333

原创 浮点数平方根,立方根 c++

//平方根#include <iostream>#include <algorithm>using namespace std;int main() { double n = 1e-5; //小数点5位 double target = 0.9; //要算平方根的数 double l = 0; //左边界 double r = max(1.0, target); //右边界,必须大于1 while (r - l > n) { double mid = (r

2022-04-28 20:46:58 2150 2

原创 声明对象指针

#include <iostream>using namespace std;class A {public: A() { cout << "AAA" << endl; } A(int a) { cout << "AAAaaa" << endl; }};int main() { A a(2); //调用1次 cout << "1111111

2022-04-14 11:31:15 174

原创 普通成员函数调用虚函数

#include <iostream>using namespace std;class A {public: void func() { printFunc(); }protected: virtual void printFunc() { cout << "AAAA" << endl; }};class B : public A {public: void func() {

2022-04-14 11:22:25 354

原创 c++工业级单例模式

网上太多的博客都是抄来抄去,对于单例模式的描述实在是难以捉摸。于是我在找了一个开源的深度学习框架,研究了一下里面的单例实现,并有了自己的理解,写下该博客作为记录。单例跟线程同步应该是两个问题,这样子能更方便更准确控制单例的生命周期,应该把同步问题交给开发者去处理。所有的单例应该在主线程去创建和销毁,如果单例内存在某个成员需要并发,那么单独对这个成员加锁就可以了。优点:任意一个类都可以通过Global模板成为单例可以用统一的New接口创建各种类单例,并支持构造重载可以精确控制单例对象的生命周期和依

2022-04-07 11:49:28 493

原创 explicit 关键字 c++

#include <iostream>using namespace std; class A{public: A(int i = 5) { m_a = i; }private: int m_a;}; int main(){ A s; //我们会发现,我们没有重载'='运算符,但是却可以把内置的int类型赋值给了对象A. s = 10; //实际上,10被隐式转换成了下面的形式,所以才能这样.

2022-04-04 09:46:31 746

原创 类模板与函数模板 C++实现

#include <iostream>using namespace std;//函数模板template<class T>void myswap(T &a, T &b) { T temp = a; a = b; b = temp;}//类模板template<class T>class A {public: A(T a, T b) { this->m_a = a; this->m_b = b; } vo

2022-04-02 17:42:18 536

原创 c++ 手写堆 (包括建堆、排序、添加元素、删除元素)

快排和归并排序点这里c++进阶之路堆排序跟快排一样是原地操作的一种不稳定排序算法。堆排序分为建堆和调整堆。建堆是通过自底向上父节点和子节点两两比较并交换得到的,时间复杂度为O(n)调整堆需要交换n-1次堆顶元素,并调整堆,调整堆的过程就是满二叉树的深度logn,所以时间复杂度为O(nlogn),所以最终时间复杂度为O(nlogn)。每次都是只操作一个数据,没有额外的辅助空间,空间复杂度为O(1)。添加元素,需要添加到最后面,也就是最右边的叶子节点,然后自下而上进行调整,直到son < p

2022-04-02 11:04:06 2456

原创 交替打印ABC多线程(互斥量+条件变量)

#include <iostream>#include <thread>#include <mutex>#include <condition_variable>using namespace std;mutex mymutex; //全局锁condition_variable cv;//全局条件变量int flag = 0;void func_a() { unique_lock<mutex> locka(mymutex);

2022-03-29 20:04:59 328

原创 c++保存数据为txt格式

本文是记录一个常用功能,经常使用但每次查找都非常不方便,因此记录一下过程,以便查阅。注意:保存的数据为浮点数时,在向文件流中添加数据时可以通过setprecision(4)设置保存数据的小数点位数#include <iostream>#include <fstream> // c++文件操作#include <iomanip> // 设置输出格式using namespace std;int main(int argc, char const *argv[

2022-02-25 15:33:45 4859 2

原创 多线程的顺序执行(信号量,POXIS标准)

方法1,信号量//使用信号量实现多线程的顺序执行#include <stdio.h>#include <semaphore.h>#include <stdlib.h>#include <pthread.h>#include <unistd.h>sem_t sem_a, sem_b, sem_c;void *fun_a() { while (1) { sem_wait(&sem_a);

2021-12-29 16:07:04 617

原创 emplace_back优势在哪里?

先贴上c++11升级版的push_back源码,实则是在传入右值时,调用emplace_back();下面做了个测试:class A {public: A() { cout << "默认构造" << endl; } A(int a) { cout << "有参构造" << endl; } ~A() { cout << "析构函数" << endl; } A(A&& a) { cout

2021-12-29 10:22:06 623

原创 TCP“粘包”是什么?

我认为TCP粘包这个概念其实不太准确,因为TCP协议本身的特性就是基于字节流的传输协议,对于TCP层来说,是不存在粘包的概念的。我们常说的粘包,应该是基于TCP协议的应用层需要在读取数据时候面对的问题。所以TCP如何解决粘包也可以理解成应用层协议如何解析字节流数据。造成粘包现象的原因可以分为三种:①tcp协议本身的流式传输特性决定了接收端可以把发送方多次发送的数据一次接收到。②TCP协议为了提高传输效率而启用了TCP_NODELAY,也就是Nagle算法,可以把间隔短、数据量小的数据合并一起,等待缓冲

2021-12-17 20:26:44 685

原创 手动创建二叉树-ACM模式

按层序遍历创建create打印的话可以任意选择一种方式打印,这里选层序了,方便直观要是改成前序的话更简单,把print函数改成递归的前序遍历就可以了#include <bits/stdc++.h>using namespace std;struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(nullptr), right(nul

2021-12-04 20:24:08 2938

原创 快速排序算法 和 归并排序算法

快排的思想是基于分治的,就是把问题切分再分别进行处理。①随机选择一个分界点,常用的是中点,假设中点的值为midVal②在数组的左边界和有边界,分别用一个指针开始往中间扫描,当遇到不合条件的时候就停下来,等到双方都停下来之后再互相交换。left指针遇到比midVal大的值时会停下来,否则继续扫描。right指针遇到比midVal小的值是会停下来,否则继续往中间靠拢。当left和right都停下来时,交换。即把小于等于midVal的放在左边,大于等于midVal的放右边③递归处理#include

2021-12-04 17:28:31 199

原创 多态(虚函数)

多态分为静态多态和动态多态,一般我们说的多态都是动态多态静态多态:程序在编译阶段就确定好地址。(函数重载、运算符重载、复用函数名)动态多态:程序在运行阶段才会确定地址。(派生类和虚函数实现运行时多态)(下面说的多态默认是动态多态)多态满足的条件:①有继承关系②子类重写父类中的虚函数(重写是指函数的返回值类型、函数名、参数列表完全一致)多态的使用:③父类指针或引用指向子类对象一个基类,如果只有一个普通的成员函数,那么sizeof这个基类的大小是1,因为需要有一个char类型的地址指向该基类

2021-11-06 10:05:43 188

原创 智能指针的实现

(实现代码做了详细的注释)内存有四块:全局区、栈区、堆区、代码区全局区存放着的是等到程序结束前才会释放里面的数据代码区是存放着编译后的二进制的0和1栈区:压栈、出栈,会自动管理释放堆区:new出来的需要手动delete,由程序员管理而智能指针的实现是利用了栈区和堆区的存储特性来实现的。一、对象开辟在栈区,析构函数会自动释放内存class Person{public: Person(int age) { this->m_age = age; } ~Person() { c

2021-11-05 10:48:03 289

原创 C++对象模型初探

成员变量和成员函数是分开存储的,意思就是说,成员函数严格来说不属于类的。C语言中的结构体是只存放变量,要在结构体之外声明定义实现函数。C++抽象出类的思想,把成员变量和成员函数封装在一个类中。C++在代码编写的时候看起来好像的确是把二者放在类内一起写,但是实际上成员函数跟成员变量是分开存储的。成员变量是属于类的,而成员函数则像静态成员函数一样是一块共享的数据,他们不属于类。因此当同一个类的不同对象访问同一个成员函数时,实际上是访问同一块地址空间。只有非静态成员变量才属于对象身上。类内的数据和操作是分.

2021-11-04 14:58:14 125

原创 梳理IO网络模型

IO网络模型是网络编程里面很重要的内容,我自己在刚开始学习的时候有的地方没有理解清楚,现在回过头来梳理串起来。首先,有几个概念需要知道:流:可以进行IO操作的内核对象,比如文件、管道、套接字等。可以把流想象成是内核里面的一个用来通信的容器,而这个容器的入口和出口都是文件描述符fd。IO操作:严格的说法应该是处理器访问任何寄存器和缓存等封装以外的数据资源都可以当成 I/O 操作,包括内存,磁盘,显卡等外部设备。而一般软件系统的 I/O 通常指磁盘和网络,而我们现在谈的是网络编程,因此可以把IO操作.

2021-11-01 22:59:01 160

原创 mysql学习笔记

英语单词都认识的话,mysql的基本使用方法不难。难的地方在于应用场景和设计思路以及优化方案。1、sql、DB、DBMS分别是什么,他们之间的关系?DB: database 数据库,实际上是以文件的方式存储在硬盘中;DBMS:database management system数据库管理系统,我们常说的mysql数据库其实不太准确,准确来说mysql属于一种数据库管理系统;SQL:称成为sql语句,结构化查询语言,是一门高级语言,同样需要先编译再执行。标准sql适用于所有的数据库产品,DBMS负

2021-10-31 18:18:57 163

原创 死锁(操作系统)

死锁: 各进程互相等待对方手里的资源,导致各进程都阻塞,无法向前推进的现象。死锁一定是“循环等待对方手里的资源”导致的,因此如果有死锁现象,那么至少有两个或者两个以上的进程同时发生死锁。另外,发生死锁的进程一定是处于阻塞状态。饥饿:由于长期得不到想要的资源,某进程无法向前推进的现象。(比如在短进程优先SPF算法中,如果一直有短进程到来,则长进程一直得不到处理机,从而发生长进程“饥饿”);可能只有一个进程发生饥饿。发生饥饿的进程可能是阻塞态(如长期得不到需要的IO设备),也可能是就绪态(比如长期.

2021-07-31 17:13:06 827

原创 管程是一种高级的同步机制(操作系统)

为什么引入管程?因为信号量机制存在的问题:编写程序困难、容易出错,因此引入管程解决这个问题,不再需要复杂的PV操作。管程跟PV操作一样也是用来实现进程的互斥和同步的。为什么要实现进程的互斥同步呢?因为进程之间可能会共享某些资源,为了实现进程对资源的互斥或共享的访问。管程是一种特殊的软件模块,有这些部分组成:1.局部于管程的共享数据结构说明。(例如生产者消费者模型里面的缓冲区就可以用这种数据结构来说明)2.对该数据结构进行操作的一组过程(过程其实就是函数)3.管程内的数据结构要进行初始化4.管程

2021-07-31 11:02:54 969 2

原创 信号量机制

一个信号量对应一种资源信号量的值 = 这种资源的剩余数量(信号量的值如果小于0,说明此时有进程在等待这种资源)实现进程互斥P——申请一个资源,如果资源不够,那就会阻塞V——释放一个资源,如果有进程在等待该资源,则唤醒阻塞队列队头的进程1.分析并发进程的关键活动,划定临界区(如对临界资源打印机的访问就放在临界区)2.设置互斥信号量mutex,初值设为1(表示进入临界区的名额数量,初始值为1,说明一开始能进入临界区的名额只有1个)//记录型信号量结构体typedef struct { int

2021-07-31 10:24:09 322

原创 运算符重载

+ 加号运算符重载class Person {public: int m_A; int m_A; }; Person p1; p1.m_A = 10; p1.m_B = 20; Person p2; p2.m_A = 10; p2.m_B = 20; Person p3 = p1 + p2;//要重载这个+号,才能正确执行下面是通过成员函数重载+号,要写在Person类里面,这里为了清晰一点所以才抽出来写Person operator+ (Person &p

2021-07-30 17:31:33 115

原创 静态成员变量和静态成员函数

静态成员变量通常要在类内声明,类外初始化,编译阶段就会分配内存,所有的对象共享一块内存而且通常用类名去访问重点注意:静态成员变量是共享一块内存的,也就是说后面给这个变量赋值会覆盖先前的值,同一块地址只能有一个值。clas Person {public: static int m_age;//类内声明private: static int m_high;//私有权限也是一样的,加上作用域之后类外直接初始化就ok };int Person::m_age = 10;//类外初始化,私有和公有是一

2021-07-25 14:46:21 193

原创 操作系统——进程状态的转换

2021-07-24 21:49:13 90

原创 一文搞清面试高频问题:深拷贝和浅拷贝(C++)

浅拷贝: 简单的赋值拷贝,默认的拷贝函数就是浅拷贝,可以理解成C++的引用,别名。新对象是旧对象的引用。深拷贝: 在堆区重新申请内存空间,再进行拷贝操作。这样就是高级的复制,新对象跟旧对象表面看起来值都一样,但是新对象跟旧对象没有其他任何关系,每个元素对应的地址是不同的。举个例子:浅拷贝就是,两个一模一样的彭于晏,一个叫彭于晏1号,另外一个叫彭于晏2号,这两个人完全一模一样复制出来的,只是叫法不同。深拷贝就是,猪八戒整容变成了彭于晏,包括身高、五官、所有的外形、声音、气质都跟整得跟彭于晏的一样,但是

2021-07-24 16:59:09 295

原创 数据的表示和运算

1、 二进制、八进制、十六进制2、 BCD码(是一种二进制的数字编码形式,用二进制编码的十进制代码)

2021-07-23 20:24:33 65

原创 浅谈extern(C++)

首先要知道使用场景:在C++的程序中想要调用C语言的程序中函数因为C++是有函数重载的,而C语言是没有函数重载的而函数重载,编译器会自动改变函数名字,比如void add(int a, int b);比如这个函数,编译器可能会自动改变函数名字为:_addv,因此如果此时要使用别的源文件或者头文件中的C语言函数,则会报错:无法连接的外部命令因此在这种使用场景下,不能够像普通C++程序一样,只包括了那个想要用的函数的头文件就可以了。这里不能包括那个函数的头文件,应该直接用 extern void

2021-07-23 16:16:44 88

原创 浅谈内联函数(C++)

内联函数实质上是空间换时间,因为函数调用的时候存在压栈和出栈,会存在消耗,内存是没有额外消耗的,因为在函数调用结束的时候会释放内存,所以普通的函数调用只是费多了一点时间。如果用内联函数,则在调用函数的时候直接“内联展开”,直接在调用函数的时候就执行了函数体内部的函数逻辑,不需要额外的内存来进行操作函数体内部逻辑。类里面的成员函数默认为内联函数。如果函数声明的时候标明了inline,那么实现的时候也要标明inline,否则只有声明的inline而没有函数实现的inline,仍然会当作普通函数调用。既然内

2021-07-23 15:02:40 428

原创 计算机硬件的基本组成(计算机组成原理)

计算机硬件的基本组成一、冯诺依曼机的结构 和 现代计算机的结构![在这里插入图片描述](https://img-blog.csdnimg.cn/3ae3ffed533941d4aa3d95614c2643e5.png ==600x350)冯诺依曼体系结构冯·诺依曼理论重要的两点是:程序存储、二进制。冯诺依曼提出“存储程序”原理,即把程序本身当作数据来对待,程序和该程序处理的数据用同样的方式储存,以此为基础的计算机称为冯诺依曼机。特点:①计算机由运算器,控制器,存储器,输入和输出五部分组成②指

2021-07-22 22:34:30 1137

原创 引用的实质(C++)

引用的实质是指针常量int a = 10;int &b = a; 自动转换成 int* const b = &a; //这也是为什么引用必须初始化的原因,指针常量必须初始化//b是一个指针常量,说明该指针是一个常量,也就是指针指向的地址不能改变,指向的这个地址的值可以改变b = 20; 内部发现是引用,则自动转换成 *b = 20;//b是一个指针,因此解引用之后取得该指针指向的地址的值,通过修改这个值,可以同时改变a的值常量引用非法操作: int &a =

2021-07-22 17:32:15 179

原创 const分配内存、伪常量(C++)

只要const可以分配内存,则可以通过指针操作,绕过编译器检测,去修改这个const修饰的变量。(const修饰的变量叫做常量,会不会觉得很疑惑?常量居然可以修改,其实这不是严格意思的常量,可以称为伪常量)情况1:当初始化定义在函数内(不是全局)const int a = 10; // extern const int a = 10 加上extren也同理int *p = (int*)&a;当初始化p指针用来取a的地址的时候才会执行一下操作:这里的const初始化是没有给a分配内存的,

2021-07-22 16:19:10 290

原创 双指针—最长连续不重复子序列

经典题,用数组处理重复#include<iostream>using namespace std;const int N = 100010;int n ;int a[N],s[N];int main(){ cin>>n; for(int i = 0 ; i < n ; i ++ ) cin>>a[i]; int j = 0,res = 0; for(int i = 0 ; i < n ; i ++ ){

2021-07-17 09:09:41 63

空空如也

空空如也

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

TA关注的人

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