自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(41)
  • 资源 (3)
  • 收藏
  • 关注

原创 Log persist实现

Log persist是将raft的Log、currentTerm和voterfor这三个数据持久化存储在磁盘里,这样当系统崩溃时,我们能从磁盘中读取持久化的数据。在本文的实现中,因为是在一台电脑中通过网络模拟了分布式场景。所以,本文是通过Go的bytes.buffer实现持久化存储。一. bytes.bufferbytes.buffer是一个缓冲byte类型的缓冲器,其存放数据都是byte。而buffer是bytes中的一个type buffer struct{}。其是一个变长的buffer,..

2021-08-26 00:50:38 247

原创 Raft协议如何保证不删除已提交日志和避免提交前任未提交日志?

一. 参考paper对于raft协议 《In Search of an Understandable Consensus Algorithm (Extended Version)》一文做了非常细致且严谨的论述,且对如何实现也做了非常细致的指导,兼具学术与工程,强烈推荐直接阅读英文原文,另MIT6.824课程的Robert Morris教授对其做了非常细致的讲解。英文原文:https://pdos.csail.mit.edu/6.824/papers/raft-extended.pdf中文译文:h

2021-08-26 00:45:38 935

原创 为什么要持久化存储log、currentTerm和votefor?

在raft论文中,有且仅有三个数据需要持久化存储,分别是Log、currentTerm和votefor。对于Log我们能够很好的理解,因为其记录了应用程序的状态。当服务重启时,我们能通存储的Log重建应用程序的状态。那为什么必须存储currentTerm和votefor呢?还有为什么仅仅只需存储这三个数据?一. 为什么必须存储currentTerm和votefor?1.1为什么存储voterfor?保证每个任期最多只有一个Leader!考虑如下一种场景:因为在raft协议中每个任期内..

2021-08-25 01:31:38 576

原创 Raft协议问题总结(二): 冲突Term和Index的回退优化

一. 问题背景在raft协议中,Leader使所有的follower的log与其保持一致,出现不一致的情况时,Leader就会改动follower的日志。其实现保持一致原理为:每个Leader会为每个follower维护一个nextIndex,其初始值为每个新任Leader的最后一条日志的下一条日志Index。并且,Leader向follower发现的广播消息中,包含了一prevLogIndex、prevLogTerm,并且preLogIndex = nextIndex -1、preLogTer

2021-08-25 01:30:27 1032

原创 Raft协议问题总结(一): Leader 选举的异步选举与提前决策

一. 问题背景在raft协议的运行中,可能会由于网络故障、机器故障等等原因使先前的Leader挂掉。而raft有一个timeout机制,即如果follower超过timeout时间没有收到来自Leader的广播,便会成为Candidate开始选举试图成为Leader。1.1 Leader选举Leader选举的流程如代码所示,首先执行Candidate逻辑,决定哪个raft节点成为Candidatem,并通过随机时间机制保证每个时间点有劲仅有一个节点成为Candidate;然后,Candida

2021-08-25 01:26:10 445

原创 2. C++ arraynew、malloc和free中的cookie

2. C++ arraynew、malloc和free中的cookie一. arraynew and deletenew原理由图可见,new A[size](size=3)时,构造函数被调用了三次:分别先[0]、后[1]再[2];delete [] A时,析构函数次序逆反也调用了三次:分别先[2]、后[1]再[0]。注意:如果delete [] A去掉[],会发生内存泄漏,具体见下文。模拟与结果#include <iostream>#include <str

2021-04-03 16:29:29 321

原创 一. C++内存分配方法、new/delete源码及new模拟

一. C++内存分配方法及new/delete源码目录一. C++内存分配方法及new/delete源码一. C++内存分配工具二. 内存分配工具间关系三. new/delete源码new源码delete源码四. new/delete操作模拟仿照模拟:侯捷源码一. C++内存分配工具1. malloc()和free()2. new和delete3. ::operator new()和::operator delete()4. allocator&l

2021-04-03 14:18:48 658

原创 二叉树的递归、层次建立/遍历和其递归/层次镜像

一. 二叉树的节点代码

2021-02-01 23:31:49 214

原创 数据结构:单链表创建、结点插入、删除代码

基于C++的实现#define _CRI_SECURE_NO_WARNINGS#include<iostream>#include"stdlib.h"#include"time.h"using namespace std;constexpr auto maxsize = 20;constexpr auto OK = 1;constexpr auto ERROR = 0;constexpr auto TRUE = 1;constexpr auto FAlSE = 0;

2021-01-04 23:38:34 919

原创 十七. C++多态详解

多态C++支持编译时多态(静态多态)和运动时多态(动态多态),运算符重载和函数重载就是编译时多态,而派生类和虚函数实现运动时多态。静态多态和动态多态的区别在于函数地址是早绑定(静态联编)还是晚绑定(动态联编)。如果函数的调用,在编译阶段可以确定函数的调用地址并产生代码,就是静态多态,就是说地址是早绑定的。而如果函数的调用,其地址不能编译不能在编译期间确定,而需要在运行时才能确定,这就是属于晚绑定(动态联邦、运行时多态)。多态成立条件:继承 子类重写父类虚函数(与父类完全一致,子类这种vir

2020-12-30 14:27:30 211

原创 十六. C++继承与派生

为什么需要继承?继承:减少代码重复内容。C++通过继承机制可以利用已有的数据类型来定义新的数据类型,新的类不仅拥有旧类的成员,还拥有新定义的成员。一个B类继承于A类,或称从A类派生类B。这样的话,类A成为基类,类B成为派生类。派生类的成员,包含两大部分:一类是从基类继承过来的,一类是自己增加的成员 从基类继承过来的表现其共性,而新增的成员体现了其个性派生类继承方式:#define _CRI_SECURE_NO_WARNINGS#define _CRT_SECURE_NO_

2020-12-29 22:32:16 85

原创 十五. C++运算符重载

目录运算符重载概念语法:重载+友元常用运算符重载加号运算符重载前置后置自增(++)运算符重载前置++运算符重载后置++运算符重载左移运算符(<<)重载指针运算符重载赋值运算符重载关系运算符重载函数调用运算符重载运算符重载概念在c++中,可以定义一个处理类的新运算符。这种定义很像一个普通的函数定义,只是函数的名字由关键字operator及其紧跟的运算符组成。差别仅此而已。它像任何其他函数一样也是一个函数,当编译器遇到适当的模式时,就会调用

2020-12-29 17:18:30 170

原创 十四. C++友元

目录友元友元语法友元类注意事项全局函数做友元函数代码实例类做有元类成员函数作为友元友元类的私有成员无法在类的外部访问。然后,有时我们需要在类的外部访问类的私有成员。解决这一访问问题的方法就是友元函数。我们可以将一个全局函数、某个类中的成员函数、甚至整个类声明为友元。友元语法friend关键字只出现在声明处 其他类、类成员函数、全局函数都可以声明为友元 友元函数不是类的成员,不带this指针 友元函数可以访问对象任意成员属性,包括私有属性友元类注意事项

2020-12-29 12:21:37 83

原创 十三. C++面对对象模型

目录成员变量和函数的存储代码实例this指针this指针工作原理this指针的使用代码实例const修饰成员函数和对象成员变量和函数的存储在C++中,数据和函数是分开存储的。C++中的非静态数据成员直接内含在类对象中。 成员函数虽然内含在class声明之内,却不出现在对象中。 每一个非内联成员函数(non-inline member function)只会诞生一份函数实例.代码实例此代码输出为:size of (Person) 16(因为对齐)#def

2020-12-29 10:50:40 95

原创 十二. C++静态成员变量和函数

静态成员在类定义中,它的成员(包括成员变量和成员函数),这些成员可以用关键字static声明为静态的,称为静态成员。不管这个类创建了多少个对象,静态成员只有一个拷贝,这个拷贝被所有属于这个类的对象共享。静态成员变量在一个类中,若将一个成员变量声明为static,这种成员称为静态成员变量。与一般的数据成员不同,无论建立了多少个对象,都只有一个静态数据的拷贝。静态成员变量,属于某个类,所有对象共享。静态变量,是在编译阶段就分配空间,对象还没有创建时,就已经分配空间。静态成员变量必须在类中

2020-12-29 09:56:57 101

原创 十一. C++动态对象创建:new与delete详解

malloc分配内存的问题程序员必须确定对象的长度。 malloc返回一个void*指针,C++不允许将void*赋值给其他任何指针,必须强转。 malloc可能申请内存失败,所以必须判断返回值来确保内存分配成功。 用户在使用对象之前必须记住对他的初始化,构造函数不能显示调用初始化(构造函数由编译器调用),用户可能忘记调用初始化函数。malloc实例class Person{public: Person(){ mAge = 20; pName = (char*)malloc(s

2020-12-29 00:47:32 849

原创 十. C++初始化列表和explicit关键字

初始化列表代码实例#define _CRI_SECURE_NO_WARNINGS#define _CRT_SECURE_NO_WARNINGS#include<iostream>using namespace std;class Person{public: Person() {} int m_A; int m_B; int m_C; //有参构造初始化数据 /* Person(int a, int b,int c) { m_A = a; m_B =

2020-12-28 23:49:27 124

原创 九. C++中拷贝构造的调用时机、浅拷贝和深拷贝

C++中拷贝构造的调用时机、浅拷贝和深拷贝C++中拷贝构造函数的调用时机用一个对象初始化另一个对象 对象以值传递的方式传给函数参数 函数局部对象以值传递的方式从函数返回#define _CRI_SECURE_NO_WARNINGS#include<iostream>using namespace std;class Person{public: Person() { cout << "默认构造函数调用" << endl; } Per

2020-12-28 23:19:55 216

原创 八. C++对象的构造和析构

目录C++对象的构造和析构初始化和清理构造函数和析构函数构造函数语法析构函数语法代码实例构造函数的分类、调用方法和调用规则分类和调用方法调用规则C++对象的构造和析构初始化和清理C++中的面对对象思想源于现实,是对现实事物的抽象,具体来说,当我们创建对象的时候,这个对象应该有一初始状态,当对象销毁之前应该销毁自己创建的一些数据。对象的初始化和清理也是两个非常重要的安全问题,一个对象或者变量没有初始化时,对其使用后果是未知的。同样,使用完一个变量没有及时清理

2020-12-28 22:21:48 125

原创 七. C/C++的封装及私有成员

目录类的封装C语言下封装的缺陷C++中的封装建议将成员变量设置为private类的封装现实世界的事物都具有自己的行为和属性,如果我们将其属性和行为表示出来,那么就可以抽象这个事物。C语言下封装的缺陷而在C语言中,因为struct仅仅能定义成员变量,而不能定义函数。这就意味着属性和行为是分开的。这时会发生一些错误,见如下代码实例:#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stri

2020-12-28 20:38:37 478

原创 六. C++函数重载与extern “C”浅析

函数重载同一个字在不同场景下具有不同的含义。C++中也有类似的现象出现,同一函数名在不同场景下可以具有不同的含义。在传统的C语言中,函数名必须是唯一的,程序中不允许出现同名的函数。在C++中是允许出现同名的函数,这种现象称为函数重载。重载的目的就是为了方便的使用函数名。实现函数重载的条件同一个作用域 参数个数不同 参数类型不同 参数顺序不同注:函数返回值不能作为重载的条件。//函数重载条件namespace A{ void MyFunc(){ cout << "无参

2020-12-28 19:52:46 300

原创 五. C++默认参数和占位参数

默认参数c++在声明函数原型的时可为一个或者多个参数指定默认(缺省)的参数值,当函数调用的时候如果没有指定这个值,编译器会自动用默认值代替。注意点:一个形参设置默认值,后面位置的形参也需要设置默认参 如果函数声明和函数定义分开,函数声明设置了默认参数,函数定义不能在设置默认参数void TestFunc01(int a = 10, int b = 20){ cout << "a + b = " << a + b << endl;}//注意点:/

2020-12-28 17:27:38 438

原创 四. C++中的引用及其本质

引用基本用法引用的简单理解引用是C++对C的重要扩充。其也存在与与JAVA、Go等语言中,对于引用,首先:变量名实质上是一段连续内存空间的别名、是一个标号(门牌号) 程序通过变量来申请并命名内存空间 通过变量的名字可以使用存储空间因此,C++中的引用可以看多一个已定义变量的别名。其基本语法为 Type & ref=val。引用注意实项&在此不是求址运算,而是起到标识作用。 类型标识符是指目标变量的类型。 必须在声明引用变量时初始化。 引用初始化后不能改变(不能

2020-12-28 17:06:52 94

原创 三. C/C++中const异同总结

目录C/C++全局变量C/C++局部变量CC++指针不可修改(const int a = 10)指针可修改(变量初始化、自定义数据类型)用const替代#define#define MAX 1024cosnt和#define区别C/C++全局变量1. c语言中全局const会被存储到只读数据段。而C++中全局const当声明extern或者对变量取地址时,编译器会分配存储地址,变量存储在只读数据段。 const int constA = 10; int m

2020-12-28 14:44:14 116

原创 二. C++对C的增强

C++对C的增强可总结为:1. 全局变量检测增强2. 函数检测增强:参数类型增强、返回值检测增强、函数调用参数检测增强3. 类型转换检测增强4. 结构体struct增强:C++中可以加函数,C使用时不可加函数。另外C使用时必须加struct:(如:struct Person p1),C++可不加5. bool类型增强,只有真或假6. 三目运算符增强7. const增强; C中可以用指针改,而C++不可以1. 全局变量检测增强int a;int a = 10; 此会报

2020-12-28 11:33:16 107

原创 一. C++: 命名空间namespace与using指令

命名空间namespaceC++命名空间的使用是为了防止名称冲突,引入关键字namespace可以更好地控制标识符的作用域。其语法特点如下:1. 命名空间下可以放符号常量、函数、变量、结构体、类和对象等等。2. 命名空间只能全局范围内定义3. 命名空间可以嵌套命名空间4. 命名空间是开放的,即可以随时把新的成员加入已有的命名空间中5. 无名命名空间(匿名命名空间)意味着命名空间中的标识符只能在文本文件内访问,相当于给这个标识符加上了static, 使其可以作为内部连接6. 命

2020-12-28 11:05:14 358

原创 十五. Go学习:goroute和cahnnel

进程和线程进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。线程是进程的一个执行实体,是cpu调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。一个进程可以创建和撤销多个线程;同一个进程中的多个线程之间可以并发执行。并发和并行多线程程序在一个核的CPU上运行,就是并发。多线程程序在多个核的CPU上运行,就是并行。协程和线程协程:独立的栈空间,共享堆空间,调度由用户自己控制,本质上有点类似于用户级线程,这些用户级线程的调度也是自己实现的。

2020-12-27 22:03:27 191

原创 十四. Go学习:锁机制

线程同步时,可能会有多个线程需要使用这个资源,为了避免资源竞争,我们需要锁机制。1. import("sync")2. 互斥锁,var mu sync.Mutex2. 读写所, var mu sync.RWMutex互斥锁package mainimport ( "fmt" "math/rand" "sync" "sync/atomic" "time")var lock sync.Mutexfunc testMap() { var a map[int]int

2020-12-26 17:38:59 351

原创 十三. Go学习:Json协议

Json用途Json数据协议1. 导入包:import "encoding/json"2. 序列化:json.Marshal(data interface{})3. 反序列化:json.UnMarshal(data []byte,v intface{})代码范例package mainimport ( "encoding/json" "fmt")type User struct { UserName string NickName string Age

2020-12-24 17:29:38 168 1

原创 十一. Go学习:反射详解

目录反射概念:动态获取interface{}的值、类型动态的改变interface()值反射操作结构体反射概念:可以动态获取变量的相关信息 import "reflect"两个函数:a. reflect.TypeOf,获取变量的类型,返回reflect.Type类型 b. reflect.ValueOf,获取变量的值,返回reflect.Value类型 c. reflect.Value.King,...

2020-12-23 17:08:45 74

原创 十. Go学习:接口详解

接口概念Go语言提供了接口(interface)这类数据类型,其把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。Interface可以定义一组方法,而这些方法在interface(){}里是不需要实现的,且其中不能包含任何变量。在Go中的接口我们在外部实现时,只需一个变量含有接口类型中的所有方法,那么这个变量就实现了这个接口。与此同时,如果一个变量同时含有了多个interface类型的方法,那么这个变量就实现了多个接口。需要我们注意的是,如果一个变量只含有一个

2020-12-23 14:11:26 141

原创 九. Go学习:Go中的继承

从下面的两段代码中可以非常直观的看出,Go中的继承跟C++相比较而言是非常方便的单重继承package mainimport "fmt"//---------------单重继承----------------type Car struct { weight int name string}func (p *Car) Run() { fmt.Println("running")}type Bike struct { Car lunzi int}func main()

2020-12-23 00:35:04 132

原创 八. Go学习:结构体的工厂模式、tag的使用、匿名字段和方法

本文总结了结构体的工厂模式、tag的使用、匿名字段和方法目录struct的工厂模式struct中tag的使用匿名字段方法struct的工厂模式Go中的struct无构造函数,我们可通过工厂模式初始化package mainimport "fmt"//工厂模式,Go中无结构体,我们用工厂模式代替type student struct { Name string Age int}func NewStudent(name string, age int) *s

2020-12-23 00:27:28 243 1

原创 七. Go学习:排序、结构体、链表和二叉树

本文介绍了结构体这一自定义数据类型,以及排序(冒泡、简单选择、插入和快爬)、链表和二叉树这三种简单的数据结构(通过代码)目录排序一. 冒泡排序二. 简单选择排序三. 插入排序四. 快速排序结构体链表二叉树排序一. 冒泡排序冒泡排序:从小往上两两比较相邻记录的关键字,反序则交换,直至有序。最小数像泡泡一样从小往上走.package mainimport ( "fmt")func sortBuble(a []int) { for i := 0;

2020-12-22 22:12:54 139

原创 六. Go学习:map数据结构

目录map一. map简介二. map相关操作三. map为引用类型四. Map的遍历五. map排序六. slice of mapmap一. map简介key-value的数据结构,又叫字典或关联数组。声明:var map1 map[keytype]valuetype—如:var a map[string]string;var a map[string]int;var a map[int]string;var a map[string]map[string]st

2020-12-22 20:23:11 135

原创 五. Go学习-数组、切片与排序查找

本文总结了Go中数组和切片的各自特点以及区别。目录数组一.数组的特性​二. 数组的初始化切片一. 切片特性二. 切片的数据结构三. 切片的make创建、apeend操作、拷贝及扩容前后变化数组一.数组的特性1)数组:是同一数据类型的固定长度的序列2)定义:var a [len] int,一旦定义,长度不能改变。因为长度也是数组类型的一部分,var a[5]int 和var a[10] int是不同的类型。3)数组可以通过下标访问,下标从0开始,最...

2020-12-22 17:12:44 508

原创 四. Go学习-make和new的区别

new和make的区别,我们从下图便可看出: 1)new是为值类型分配内存(可以任意类型的数据),其返回的是指针,指向分配类型的内存地址。 2)make为引用类型分配内存并初始化,如:chan、map和slice,其返回值为这个类型(引用)本身。 3)new 分配的空间被清零。make 分配空间后,会进行初始化; ...

2020-12-22 15:08:21 1187

原创 三. Go基础:常量和变量、值类型和引用类型、变量的作用域、单引双引反引和字符串的翻转截断

目录2.1 常量和变量2.2 值类型和引用类型2.3 变量的作用域2.4 单引双引反引2.5 字符串的翻转截断在本篇中,总结了常量和变量、值类型和引用类型、变量的作用域、单引双引反引和字符串和翻转截断这些基础概念和操作2.1 常量和变量 2.1.1 常量 常量只能用const修饰,表示仅只读而不能修改,其可修饰类型包括:bool类型、number (int、float、complex)和string,其语法为const identifier [ty...

2020-12-22 10:41:41 195

原创 二. Go中自建包的调用

Go中自建包的调用 1. 在GOPATH路径src文件夹下建文件go_dev/day1/package_example/calc夹,然后在calc文件夹下建两个go文件Sub.go和Sum.go并分别写数值相减和相加的函数,代码如下所示。 这儿需要注意的是,package main应改为package+文件名。package calcfunc Sub(a int, b int) int { return a - b}package calcfunc Sum...

2020-12-21 20:02:56 504

原创 一.Go语言特性(结合代码)

Go语言特性目录Go语言特性1.1 垃圾回收1.2 天然并发1.3 Channel1.4多值返回 Go语言有垃圾回收、天然并发、channel和支持多值返回这四个独特的特性。1.1 垃圾回收 在垃圾回收上,Go内存可自动释放,无需开发人员管理内存,new()分配的内存会自动释放。 如在链表的操作中,我们删除链表中的某个节点时,无需像C++需要用delete()删除,Go会自动释放不会产生内存泄漏。如删除student链表里的s...

2020-12-21 19:23:10 391

lenet_5模型-MATLAB代码实现

这是用于手写数字识别的lenet-5模型的MATLAB 代码,内有数据集可以直接运行

2017-10-28

斯坦福CS231课程讲义

深度学习,卷积神经网络的入门课程,对于想学习深度学习尤其是图像识别来说特别合适

2017-10-27

吴恩达机器学习课程讲义

吴恩达机器学习课程讲义

2017-08-11

空空如也

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

TA关注的人

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