自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(68)
  • 问答 (1)
  • 收藏
  • 关注

原创 python基础(二)——格式化输出

文章目录python基础(二)——格式化输出方法一:使用%s占位符输出字符串输出结果:注意:方法二:如何输出02021这样格式的数据输出结果:解析:注意:输出结果:方法三:如何保留小数输出输出结果:解析:输出结果:方法四:使用引号进行格式化输出输出结果:解析:注意:方式五:使用format进行格式化输出输出结果:注意:python基础(二)——格式化输出方法一:使用%s占位符输出字符串print('name is %s,age is %s,sex is %s' % ('ming',14,'boy'))

2022-01-07 16:41:08 1970

原创 python基础(一)——print、help函数和转义字符

python基础(一)——print、help函数和转义字符文章目录python基础(一)——print、help函数和转义字符一、print函数1、sep参数2、end参数二、help函数1、作用2、使用方法三、转义字符1、\n和\r的使用2、如何打印出转义字符方法一:使用双反斜杠方法二:在字符串前加r一、print函数1、sep参数age=19name='ming'print(age,name,sep='#')输出结果:解析:在print函数中,增加sep参数就可以添加分隔符注意

2022-01-06 18:16:47 1065

原创 深入理解进程(七)——程序替换

深入理解进程(七)——程序替换一、什么是程序替换?用一个新的程序去替换一个进程正在调度的程序的信息。二、程序替换的原理进程运行一个程序时,我们需要将该程序加载到内存中,然后再通过该进程的虚拟地址空间利用页表映射到数据实际上存放的物理内存中,通过这样的方式,就实现了进程与程序之间的关联。如果我们此时将另一个程序加载到内存中,然后修改这种映射关系(也就是修改页表),那么进程就与这个新程序关联起来,那么该进程就不再执行原来的程序,而是会去执行这个新的程序。三、程序替换的本质本质上就是去替换一个进程pc

2021-02-05 16:51:33 960

原创 深入理解进程(六)——进程等待

一、进程等待的作用父进程等待子进程退出,获取子进程的返回值,避免产生僵死进程。二、如何实现进程等待(1)wait函数1. 函数原型:pid_t wait(int *status)该函数是一个阻塞函数,功能是等待任意一个子进程退出。2. 参数说明:status:用于获取退出原因3. 返回值:返回值是退出的子进程的ID(2)waitpid函数1. 函数原型:pid_t waitpid(pid_t pid,int* status,int options)可以等待任意一个子进程退出或者等

2021-01-27 09:37:44 1047

原创 深入理解进程(五)——进程终止

深入理解进程(四)进程终止本篇介绍退出进程的三种常用方式:return、exit和_exit。一、进程退出的三种常用方法方式一:在main函数中调用return。退出时会自动刷新缓冲区,将缓冲区中的数据写入文件中方式二:调用exit函数。函数原型:void exit(int status)该函数是一个库函数,谁调用该函数那么谁就退出,并将status作为返回值返回给父进程。方式三:调用_exit接口函数原型:void _exit(int status)该函数是一个系统调用接口,同样谁调用

2021-01-26 14:35:02 250

原创 深入理解进程(四)——进程创建

本篇文章主要介绍了与进程创建有关的两个函数fork和vfork,以及他们之间的区别(1)fork函数函数原型:pid_t fork()。该函数是通过复制父进程来创建子进程。返回值:调用一次fork函数却能够返回两个值。 在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。fork出错可能的原因(1)当前的

2021-01-26 11:06:31 322

原创 深入理解进程(三)——由虚转实

深入理解进程(二)——由虚转实上一篇对虚拟地址空间做了基本的介绍,这一篇介绍操作系统是如何将虚拟地址转换为物理地址的。虚拟内存的管理主要是分为三种:分页、分段、段页。分页式管理首先要明白一些基本的知识:虚拟地址: 也就是进程一般访问的地址,其实就是虚拟地址空间中的地址。它一般是由页号和页内地址组成。物理地址: 数据真正存放的地址,一般是由操作系统来访问的。它一般是由块号和页内地址组成。页表:页号: 对应进程的哪一页块号: 对应内存的哪一块页表始址: 整个页表的开始位置页表项长度: 一

2021-01-25 15:40:08 1080

原创 深入理解进程(二)——虚拟地址空间

深入理解进程(一)——虚拟地址空间一、为什么要有虚拟地址空间?​ 在谈论虚拟地址空间之前,大家要知道一个常识:程序在运行之前是要全部加载到内存中的。假如现在有两个程序,一个大小为4M,一个大小为8M,而我们的内存大小为16M。首先我们运行4M大小的程序,将其加载到内存中,然后再运行8M大小的程序,同样将其加载到内存中,如下图所示:那么这个时候我们还剩余4M的空间,此时如果我们想要再加载一个6M大小的程序,那么肯定就加载不了,因为内存不够,但是如果这个程序的优先级很高,那么操作系统就会把4M的程序

2021-01-22 15:21:50 854

原创 环境变量

环境变量一、什么是环境变量?存有操作系统运行环境参数的变量。环境:操作系统运行环境。变量:保存数据作用:系统设置更加方便二、与环境变量有关的命令?env——查看所有的环境变量set——查看所有的变量,包含环境变量echo $变量名称——查看单个的变量内容(一定要有$符号)export——设置(添加)环境变量,可以将一个普通的变量设置为环境变量unset——将某个环境变量删除注意:直接使用PATH,表示的是一个PATH字符串,如果前面加上,表示的就是PATH是一个变量,,表

2021-01-21 17:39:55 896

原创 深入理解进程(一)—— 进程基本概念

进程基本概念一、进程是什么?两个角度来理解:对于用户来说: 进程就是一个正在运行的程序对操作系统来说: 进程就是一个正在运行的程序的信息的描述集合,我们一般称它为 pcb,这个pcb实际上是一个名为:task_struct的结构体。所以对于操作系统来说,一个个进程就是一个个pcb。用户在点击程序或文件后,程序或者文件就会运行,首先文件中的数据就会拷贝一份放入内存中,同时操作系统会创建一个PCB(创建pcb就是创建进程),PCB中会有一个内存指针指向该内存,CPU通过PCB就能对进程控制和管理

2021-01-21 17:37:05 1908 1

原创 在openresty中利用lua嵌入C程序

在openresty中利用lua嵌入C程序两个前提:已经安装openresty,若是没有安装可以前往https://blog.youkuaiyun.com/weixin_43850474/article/details/112860649查看如何安装已经学会如何在lua中调用C函数,若是不会,可以前往https://blog.youkuaiyun.com/weixin_43850474/article/details/112860725学习一、步骤展示第一步:编写C程序,假设其文件命名为:test.c该C程序功能很

2021-01-21 15:28:03 486

原创 Linux常见的操作命令

Linux常见操作命令ls命令ls——浏览当前目录下的内容,默认情况下这个目录为家目录ls 目录名称——浏览指定的目录ls -a——显示所有的文件,包括隐藏文件ls -l——显示目录下所有文件的详细信息注意:蓝色的表示目录、绿色表示可执行文件、红色表示这是个压缩包、黑色表示这是个普通文件隐藏文件是以点开头的文件pwd命令pwd——显示当前所在路径(该路径为绝对路径)注意:绝对路径:就是以起始路径是根目录来表达的路径相对路径:以当前用户所在路径为起始路径来表达的路径.

2021-01-20 15:24:21 427

原创 Linux下在lua中调用C函数动态库

在Linux中以.so结尾通常都是动态函数库。假设我现在要在lua中调用一个C函数,这个C函数的功能是输出一个数字。第一步:建立两个文件test.c、test.luavim test.cvim test.lua第二步:在test.c中编写C语言代码,代码如下://下面的三个头文件是必须包含的,是属于lua中的#include "lua.h" #include "lualib.h"#include "lauxlib.h"//下面两个头文件根据具体的C语言来确定,因为

2021-01-20 11:26:26 388

原创 openresty安装及使用

对于一些常见的 Linux 发行版本(Ubuntu、Debian、CentOS、RHEL、Fedora、OpenSUSE、Alpine 和 Amazon Linux),可以使用下面的方法。否则请参考http://openresty.org/cn/installation.htmlRHEL你可以在你的 RHEL 系统中添加 openresty 仓库,这样就可以便于未来安装或更新我们的软件包(通过 yum check-update 命令)。添加仓库,运行下面的命令(对于 RHEL 8 或以上版本,应将下面的

2021-01-20 11:21:40 728

原创 五种IO模型

五种IO模型什么叫做读就绪,什么叫做写就绪?读就绪:接受缓冲区中的数据大小,大于等于低水位标记(1字节)写就绪:发送缓冲区中的剩余空间的大小,大于等于低水位标记(1字节)一、阻塞IO用户线程发起IO请求时,内核会去查看数据是否就绪,如果数据没有就绪,那么该线程就会陷入阻塞状态,也就是说该线程这时候就不会继续向下执行,同时它也会让出CPU,直到数据就绪,那么这个时候用户线程才会进行对应的IO处理。举例说明:以套接字中的read函数举例:当我们想要读取接受缓冲区中的内容时,我们会调用read函数

2020-09-15 10:06:09 207

原创 基类与派生类对象之间的赋值问题

一、将派生类对象赋值给基类对象?注意:这不同于将派生类对象赋值给基类的引用或者指针请看如下代码:Base b; //基类对象Derived d; //派生类对象b=d; //赋值这将使用哪一个运算符呢?赋值语句实际上会被转换为下面的语句:b.operator=(d);其中左边的对象是基类对象,所以调用的是基类中的赋值运算符重载函数,右边的对象作为传入的参数。而实参与形参结合的过程实际上就是派生类对象赋值给基类对象的引用。所以,b=

2020-06-16 17:19:28 3661 1

原创 在继承体系中使用new要注意哪些?

一、派生类中不使用new在派生类中不使用new意味着,派生类中新增加的成员没有指针类型的成员。(1)派生类中是否需要显式的定义析构函数?不需要。因为在派生类中没有指针成员,所以在派生类对象生命周期结束时,使用默认的派生类的析构函数也是可以释放掉派生类中新增加的成员,然后调用基类的析构函数完成对派生类中继承下来的成员的清理工作。(2)派生类中是否需要显式的定义拷贝构造函数?不需要。因为在派生类中没有指针,所以在拷贝的过程中,先显式的调用基类的拷贝构造函数,完成对派生类中从基类继承的成员的复制,然后使

2020-06-15 19:43:51 346

原创 C++ 转换构造函数和转换函数

一、转换构造函数(1)转换构造函数的作用作用:将某种类型转换为类类型例如有下面的代码:Base(int a); //转换构造函数Base b; //对象b=12; 解析:程序将使用构造函数Base(int a)构造出一个临时的无名Base对象,并用12对其初始化。然后采用逐个成员赋值的方式将该临时对象的内容赋值给对象b。这一过程被称为隐式类型转换,因为它是自动的,不需要显式强制类型转换。(2)转换构造函数基本形式定义:只接受一个一个参数的构

2020-06-07 15:02:54 2319

原创 堆排序

这个博主对堆排序的思想、步骤 用图片的方式解释的还是很清楚的,可以直接点击这段话就可以跳转。所以我就只写代码的实现一、代码实现#include <iostream>#include <vector>using namespace std;void HeapAdjust(vector<int> &list, int parent, int length) { int temp = list[parent]; // temp保存当前父节点 i

2020-05-31 11:05:23 92

原创 归并排序

一、图解归并排序下图展示了归并排序的大致思路一、分阶段分阶段其实很好去实现,只需要使用递归就能很好的分出来二、治阶段我们需要将两个有序的序列合并成一个有序序列,具体的方法如下图所示:假如有两个有序序列【4、5、7、8】和【1、2、3、6】。二、代码实现#include <iostream>#include <vector>using namespace std;void Merge(vector<int> &input, int

2020-05-30 11:58:22 111

原创 快速排序的递归形式和非递归形式

图解快速排序假如有如下所示的一组序列

2020-05-29 12:34:55 240

原创 考虑异常安全的赋值运算符

一、赋值运算符需要考虑的因素一个赋值运算符需要考虑的因素,有以下四点:1. 检查返回值类型是否是该类类型的引用,并且返回值也是自身引用(即*this)。如果返回类型是一个void,那么就不能进行连续赋值(s1=s2=s3)。s1=s2=s3实际上是s1=(s2=s3),首先是s3对s2进行赋值,赋值完毕之后,会返回一个NULL,这就相当于s1=NULL,这样是C++不允许的,所以会出现编译错误。如果返回值不是一个引用,那么会多调用一次拷贝构造和析构函数,程序的效率相对而言会更低2. 检查函数的

2020-05-26 20:26:08 186

原创 C++ shared_ptr的线程安全问题

shared_ptr的线程安全问题首先看看下面的图,这个图描述的就是对象、资源、引用计数之间的关系。shared_ptr的线程安全问题需要从两个角度来分析:(1)从引用计数的角度来看:虽然引用计数存在于每一个shared_ptr对象中,但是实际上它是要跟随对象所管理的资源。引用计数会随着指向这块资源的shared_ptr对象的增加而增加。因此引用计数是要指向同一块资源的所有的对象共享的,所以实际上引用计数在shared_ptr底层中是以指针的形式实现的,所有的对象通过指针访问同一块空间,从而实现共

2020-05-25 13:25:07 3357

原创 C++ shared_ptr的模拟实现

一、 shared_ptr的模拟实现我在之前的博客《智能指针》中有说过shared_ptr的原理,那么这篇博客,我们模拟实现一个shared_ptr,让大家能更好的理解它的原理。include<mutex> //这个头文件是用来使用互斥锁template<class T> class Shared_ptr { public: //构造函数 Shared_ptr(T* _ptr = nullptr) :ptr(_ptr) , pcount

2020-05-25 10:09:03 577

原创 C++ unique_ptr的模拟实现

一、unique_ptr的模拟实现在之前的博客中,我说过auto_ptr的缺陷,所以为了避免auto_ptr的缺陷,所以unique_ptr用了一个简单粗暴的办法:防拷贝、防赋值。既然auto_ptr在拷贝和赋值的时候,会出现一些问题,那么在unique_ptr中就不让他进行拷贝和赋值。那么如何禁止它拷贝和赋值呢?我们都知道,如果我们没有定义拷贝构造和赋值运算符重载函数时,编译器会为其生成默认的拷贝构造和赋值运算符重载。所以我们可以用下面两种办法来实现禁止拷贝和赋值。方法一: 在C++98中将拷贝

2020-05-24 13:15:35 479

原创 C++ auto_ptr的简单模拟实现

一、auto_ptr的简单模拟实现关于auto_ptr的缺陷我在之前的博客中就已经说明。在这篇博客中我们从它的底层来更进一步阐述。在学习中,对某一个类进行简单的模拟,一般情况下,我们只需要模拟实现四个函数,分别是:构造函数、析构函数、拷贝构造函数以及赋值运算符重载。但是对于一个指针来说,它还要加上*运算符重载和->运算符重载 template<class T> class Auto_ptr { public: //构造函数 Auto_ptr(T* _ptr=NULL)

2020-05-23 14:17:56 237

原创 C++ 不在构造函数和析构函数中调用虚函数

首先在构造函数或者是在析构函数中是可以调用虚函数的。但是我们最好不要这样做。一、不在构造函数中调用虚函数当我们在构造函数中调用虚函数时,一定调用的是基类的虚函数,即使此时你定义的是一个派生类的对象。原因一:在创建派生类对象时,一定首先调用的基类的构造函数,其次在调用的是派生类构造函数。问题就在于,当程序执行到基类的构造函数时,因为还没有调用到派生类的构造函数,所以此时派生类的成员还处于未初始化的阶段,而在虚函数中几乎可以肯定它会对派生类的成员进行操作,而此时派生类中的成员还没有初始化,那么这在C++

2020-05-20 21:09:33 615

原创 C++ 智能指针

本文主要介绍C++中的四个智能指针:auto_ptr、unique_ptr、shared_ptr、weak_ptr。其中auto_ptr已经被弃用,原因我们下面说。为什么要使用智能指针?首先看下面一段代码:void func(){ int *p=new int(1); return 0;}在这段代码中,我们使用了new在堆上开辟一个空间,但是我们在函数结束的时候并没有用delet...

2020-02-27 12:56:44 261

原创 C++ 多态的原理

什么是多态?所谓的多态说简单来讲就是不同的对象去完成相同的工作时,会产生不同的状态。多态分为两种:一种是编译时的多态(静态多态),另一种是运行时的多态(动态多态)。编译时的多态编译时的多态的实现与静态连编有关。(1)那么什么是静态连编呢?所谓的连编就是将函数名和函数体的代码联系在一起的过程。而所谓的静态连编就是在编译时进行的连编。程序在编译期间,编译器通过对实参与形参的比较,对于同名的...

2020-02-23 14:24:25 160

原创 C++菱形继承与虚拟继承

C++的继承中有一种复杂的继承方式,这就是菱形继承。菱形继承(1)什么是菱形继承?假设现在有四个类,分别是A、B、C、D四个类。如果B类和C类同时继承于A类,并且D类又同时继承于B类和C类,那么这四个类之间的关系就叫做菱形继承。可以用下面的图来表示。(2)菱形继承的问题菱形继承会存在两个问题,一个是数据冗余,另外一个是二义性。我用一段简单的代码来说明这两个问题:class A{...

2020-02-22 17:36:04 263

原创 C++常类型

在C++中虽然使用了许多手段去增加数据的安全性,但是有些数据是却是需要共享的,所以这些共享的数据不免便破坏了数据的安全性。于是为了解决这样的情况,于是便出现了常类型。常类型的引入,既保证了数据的共享性又保证了数据的安全性。所谓的常类型就是以const关键字修饰的类型。C++中的常类型包括常引用、常对象、常对象成员。其中的常对象成员又包括常数据成员和常成员函数。常引用一、定义const 类型...

2020-02-11 13:01:48 286

原创 C++ 静态成员

C++中的静态成员包括静态数据成员和静态成员函数。静态数据成员一、介绍及作用在一个类中,如果在一个数据成员前冠以关键字static,那么这种数据成员就叫做静态数据成员。与一般的数据成员不同,无论建立多少个类的对象,都只有一份静态数据成员的拷贝,也就是说,静态数据成员为该类的所有对象所共享。C++支持静态数据成员的一个主要原因就是可以不必使用全局变量,因为全局变量破坏了C++封装的特点。静态...

2020-02-04 13:00:38 1170

原创 C++ 浅拷贝和深拷贝

浅拷贝所谓的浅拷贝就是调用默认的拷贝构造函数按照字节序对数据成员逐一赋值。举例说明:#define _CRT_SECURE_NO_WARNINGS#include<iostream>#include<string>using namespace std;class Student {public: Student(const char *_name, in...

2020-01-30 22:08:36 138

原创 C++拷贝构造函数

拷贝构造函数一、作用在建立一个新的对象时,用一个已经存在的对象去初始化这个新建立的对象。二、定义类名 (const 类名& 对象名){ 函数体}举例说明:class Date{public: Date(int year = 1900, int month = 1, int day = 1) { _year = year; _month = mo...

2020-01-30 20:34:34 120

原创 C++析构函数

析构函数一、作用在对象的声生命周期结束时,做一些清理工作,列如:释放给对象分配的内存空间。二、定义~类名(){ 函数体}三、特点函数名和类名相同函数名前需要加上~没有函数参数无返回值在一个类中只能有一个析构函数撤销对象时,编译器自动调用...

2020-01-30 19:44:27 84

原创 C++ 构造函数

构造函数一、作用主要用来完成对象的初始化工作。二、定义及使用构造函数的定义:类名(参数表){ 函数体}举例说明:class Date{public: //构造函数 Date(int year, int month, int day) { _year = year; _month = month; _day = day; }private:...

2020-01-29 18:47:03 234

原创 C++ 类和对象

1、结构体的扩充在C语言中,我们都学过结构体,它是一种自定义的数据类型,在结构体中我们只能定义变量 。C++语言对结构体进行了扩充,提供了一种更加安全有效的数据类型,它不仅可以在其中定义变量,还可以包含函数,这就是C++中的类。实列说明://C语言中的结构体struct student{ int age; float score; char name[20];}; //C++中...

2020-01-28 15:03:44 103

原创 内存对齐规则

内存对齐规则一、规则介绍(1)第一个成员变量在结构体变量偏移量为0的地址处(2)其他成员变量要对齐到对齐数的整数倍的地址处对齐数 = 编译器默认的一个对齐数与该成员大小的较小值。 VS中默认的值为8Linux中的默认值为4(3)结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。(4)如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就...

2020-01-28 14:58:15 286

原创 数据结构——双向循环链表

双链表的结构解析:每一个结点都有一个数据域,两个指针域。其中一个指针域指向它的直接后继,另外一个指向它的直接前驱。对于头结点来说,它的直接前驱是最后一个结点;对于最后一个结点来说,它的直接后继是头结点。所以对于双向链表来说,它的判空条件是head->next=head或者是head->prev=head下图为一个带头结点的空双链表双链表基本操作的实现(1)插入1....

2019-09-27 22:15:05 2597

原创 数据结构—单链表

一、链表(1)定义:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链。(2)链表的基本知识链表是一种动态的存储结构,所谓动态就是可以根据表中结点的个数来自动的分配合适的空间。也就是说,当插入结点时,系统自动申请一块空间,进行插入;当删除结点时,系统自动回收该结点所占用的空间,从而避免了空间的浪费。链表在物理位置上并不相邻,但是在逻辑上是相邻的。(2...

2019-09-26 14:54:36 707 2

空空如也

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

TA关注的人

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