自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 面试凉经之锐捷

1.讲一讲C语言中函数栈帧开辟的过程(1)先将调用者main()函数的堆栈的基址(ebp)入栈,以保存之前任务的信息。(2)然后将调用者main()函数的栈顶指针(esp)的值赋给ebp,作为新的基址(即被调用者函数fun()的栈底)。(3)然后在这个基址(fun()函数的栈底)上开辟(一般用sub命令)相应的空间用作被调用者fun()函数的栈空间。(4)函数fun()返回后,从当前栈帧的ebp即恢复为调用者函数main()的栈顶(esp),使栈顶恢复函数fun()被调用前的位置,然后调用者main

2020-09-26 17:37:13 321

原创 C++泛型算法

泛型算法 = template + 迭代器 + 函数对象特点一:泛型算法的参数接收的都是迭代器特点二:泛型算法的参数还可以接收函数对象sort,find,find_if,binary_search,for_each绑定器+二元函数对象 = 一元函数对象bind1st:把二元函数对象的operator(a,b)的第一个形参绑定起来bind2nd:把二元函数对象的operator(a,b)的第二个形参绑定起来#include <iostream>#include <algori

2020-09-10 23:05:27 135

原创 有序关联容器

头文件:#inlucde #include 底层数据结构:红黑树#include <iostream>#include <set>#include <map>using namespace std;int main(){ set<int> set; for (int i = 0; i < 20; ++i) { set.insert(rand() % 20 + 1); } for (

2020-09-09 22:41:59 173

原创 无序关联容器

无序关联容器底层:哈希表 增删查时间复杂度都是O(n);set:集合 key map:映射表 [key,value]unordered_set :单重集合unordered_multiset:多重集合unordered_map:单重映射表unordered_multimap:单充映射表使用无序关联容器包含的头文件#include <unordered_set>#include <uordered_map>**set集合:**常用方法函数:增加:insert

2020-09-09 17:09:48 126

原创 栈、队列以及优先级队列的容器配置相关问题

怎么理解这个适配器?1、适配器底层没有自己的数据结构,它是另外一个容器的封装,它的方法,全部由底层依赖的容器进行实现。2、没有实现自身的迭代器。为什么queue和s’tack底层不依赖vector而以来deque呢?1、vector的初始内存效率太低了,每次都是二倍扩容,deque的第二维默认是4096/sizeof(int)=1024个数组空间,不需要多次扩容。2、对于queue来说,需要支持尾部插入,头部删除,deque这两项操作的时间复杂度都是O(1),如果依赖vector,其底层出队效率很

2020-09-08 21:54:43 143

原创 vector容器与deque、list容器的对比

vector和deque之间的区别?1.底层数据结构:vector特点:动态数组,内存是连续的,2倍的方式进行扩容;deque特点:动态开辟的二维数组空间,内存并不连续,第二维是独立new出来的,属于分段连续。固定长度,扩容的时候,第一维的数组进行二倍扩容;2.前中后删除插入元素的时间复杂度:中间插入删除都是O(n),末尾插入删除都是O(1),头插deque的时间复杂度是O(1),vector是O(n);3.对于内存的使用效率vector需要的内存空间必须是连续的,deque可以分块进行数据存

2020-09-05 23:36:22 164

原创 deque与list容器简单介绍

deque:双端队列容器底层数据结构:动态开辟的二维数组,一维数组从2开始,以二倍的方式进行扩容,每次扩容后,原来第二维的数组,从新的第一维的下标oldsize/2开始存放,上下都预留相同的空行,方便支持deque的首尾元素添加。#include deque deq;增加:deq.push_back(20);从末尾添加元素 时间复杂度O(1)deq.push_front(20);从首部添加元素 时间复杂度O(1)deq.insert(it,20);在指向的位置添加元素,时间复杂度O(n)

2020-09-05 23:09:28 429

原创 vector容器

底层数据结构:动态开辟的数组,每次以原来空间大小的二倍进行扩容。头文件:#include < vector >增加:vec.push_back(20);//向容器末尾添加元素,时间复杂度O(1),可能导致容器扩容vec.insert(it, 20);//在迭代器的位置插入元素,每次插入都会导致数据位置移动,时间复杂度O(n)删除:vec.pop_back();//末尾删除元素,时间复杂度O(1)vec.erase(it);//删除迭代器指向的元素,时间复杂度O(n)查询:o

2020-09-05 21:57:51 805

原创 C++的四种类型转换

C++语言级别提供了四种类型转换方式,分别是:const_cast:去掉常量属性的一个类型转化static_cast:提供编译器认为安全的类型转换,编译时期的类型转换reinterpret_cast:类似于C风格的强制类型转换dynamic_cast:主要用在继承结构中,可以支持RTTI类型识别的上下转换,属于运行时期的类型转换const_cast例子:int main(){ const int a = 10; int *p1 = (int *)&a; int

2020-09-05 14:22:02 357

原创 多态的应用原理笔记

如何解释多态:静态(编译时期)的多态:函数重载:bool compare (int, int) {}bool campare(double, double) {}在编译阶段确定好调用的函数版本campare(10,20); call compare_int_intcampare(10.5,10.5); call campare_double_doubel模板(函数模板与类模板):templatebool campare(T a, T b) {}campare(10,20); =&g

2020-09-02 23:01:14 65

原创 虚函数以及静态绑定与动态绑定简单总结

一个类添加了虚函数,对这个类有什么影响?一个类里面定义了虚函数,那么编译阶段,编译器会给这个类类型产生一个唯一的虚函数表(vftable),虚函数表里面储存的内容主要是RTTI指针和虚函数的地址。当程序运行时,每张虚函数表都会加载到内存的.rodata区。一个类里定义了虚函数,那么这个类定义的对象,其运行时,内存中开始的部分会多储存一个vfptr虚函数指针,指向对应类型的虚函数表。一个类型定义的n个对象,vfptr指向的都是同一张虚函数表。一个类中定义多个虚函数,不会影响对象内存的大小,只会影响虚函数

2020-09-02 15:35:15 1309

原创 队列的内存池简单实现(new与delete的重载)

#include <iostream>using namespace std;template <typename T>class Queue{public: Queue() { _front = _rear = new QueueItem(); } ~Queue() { QueueItem *cur = _front; while (cur != nullptr)

2020-08-30 22:46:42 179

原创 vector容器的迭代器实现

#include <iostream>using namespace std;template<typename T>class vector{public: vector(int size = 10) { _first = new T[size]; _last = _first; _end = _first + size; } ~vector() { delete[]

2020-08-28 21:54:40 674

原创 String对象的迭代器iterator实现

class String{public: String(const char *p = nullptr) { if (p != nullptr) { _pstr = new char[strlen(p) + 1]; strcpy(_pstr, p); } else { _pstr = new char[1]; *_

2020-08-27 23:19:45 908 1

原创 String类的实现

#include <iostream>using namespace std;class String{public: String(const char *p = nullptr) { if (p != nullptr) { _pstr = new char[strlen(p) + 1]; strcpy(_pstr, p); } else {

2020-08-27 17:19:29 61

原创 进程管理中vfork函数

vfork函数的调用和返回值与fork函数的相同,但是两者的功能有所不同。1.fork创建的子进程会复制其父进程的数据段和堆栈段;vfork的父进程共享数据段。2.vfork并不会把父进程的地址空间完全复制给子进程,因为子进程会立刻调用exec或者exit,也就不会访问该地址空间,只在子进程调用exec之前,在父进程空间中运行。3.vfork函数保证子进程先运行,在它调用exec或者exit之后父进程才可以调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步操作,将会导致死锁。vfork函数

2020-08-10 23:51:40 228 1

原创 进程等待函数(waitpid)

waitpid函数原型如下:pid_t waitpid(pid_t pid , int *status , int options)与wait函数相比,系统调用二者的作用是完全相同的,但是waitpid多出了两个可由用户控制的参数pid和options。pid:从参数的名字上可以看出来这是一个进程的ID。但是这里pid的值不同时,会有不同的意义。1.pid > 0时,只等待进程ID等于pid的子进程,只要该子进程不结束,就会一直等待下去;2.pid = -1时,等待任何一个子进程的退出,此时

2020-08-10 03:30:50 9003 1

原创 进程等待函数(wait)

函数原型:int wait(int* statloc);作用:进程一旦调用了wait,就会立刻阻塞自己,由wait分析当前进程中的某个子进程是否已经退出了,如果让它找到这样一个已经变成僵尸进程的子进程,wait会收集这个子进程的信息,并将它彻底销毁后返回;如果没有找到这样一个子进程,wait会一直阻塞直到有一个出现。参数statloc用来保存被收集进程退出时的一些状态,它是一个指向int型的指针。但如果对这个子进程是如何死掉的不在乎,咱们可以将它设置为NULL:pid = wait(NULL);如果成

2020-08-09 23:12:48 2534

原创 C++编译链接原理简单介绍

编译链接阶段主要分为预编译、编译、汇编、链接这几个阶段。预编译阶段1、删除宏定义并做文本替换2、递归展开头文件3、处理预编译指令,例如#if、#endif4、删除注释5、添加行号和文件标识6、保留#pragma的命令,因为编译器还需要使用编译阶段1、词法分析2、语法分析3、语义分析4、对代码进行优化(提高效率、不可控)5、生成相应的汇编代码汇编阶段将汇编语义翻译成操作系统可以识别的二进制文件汇编阶段并没有对弱符号进行处理,也没有对符号表里面外部符号进行处理,指令段里面也存在虚

2020-07-23 23:25:07 176

原创 用C语言建立一个顺序栈

栈(stack)是一种限定只能在一端进行插入和删除的线性表。表中允许进行插入和删除操作的一端称为栈顶,表的另一端称为栈底。栈的主要特点是“先进后出”,即先入栈的元素后出栈。每次进栈的元素都会成为新的栈顶,每次出栈的元素都是当前的栈顶元素。由于栈从组成元素的逻辑关系上来看是线性结构,因此可以像线性表一样采用顺序储存结构,即分配一组连续地址的储存单元依次存放自栈底到栈顶的元素,同时设置指针top指示栈顶元素在顺序栈中的位置。顺序栈的类型定义#define INIT_SIZE 10typedef stru

2020-07-22 23:22:29 4693

原创 用C语言简单实现双向链表

在单链表中,通过一个结点找到它的后继结点非常容易,操作的时间复杂程度为O(1),但是要找到它的前驱结点非常麻烦,操作的时间复杂程度为O(n),因为只能从表头指针开始,沿着每个结点遍历,究其原因是单链表的各个结点只指向其后继结点的next域,如果希望查找前驱结点的时间复杂程度也为O(1),则需要为每个结点添加一个前驱指针域prio,使得链表可以双向查找。这就是双向链表。双向链表结点的类型定义双向链表的每个结点都有两个指针域:一个指向后继、一个指向前驱。typedef struct DNode{

2020-07-21 23:31:19 237

原创 用C语言简单实现单链表

对于长度变化较大的线性表,预先分配空间必须按照最大空间分配时,会有空间利用不充足、线性表扩容难的问题。解决这些问题的办法就是采用链式储存结构。线性表的链式储存结构是指用一组任意的储存单元储存线性表中的数据。为了反应数据元素之间的逻辑关系,对于每个数据元素,不仅要表示它的具体内容,还要附加一个表示它的直接后继元素的储存位置的信息,这两部分信息组成数据元素的存储映像,成为结点(Node)。单链表中的每个结点只包含一个指针域。在线性表的链式储存结构中,为了方便插入和删除算法的实现,每个链表附加一个头结点,并通

2020-07-21 22:24:06 379

原创 用C语言简单实现顺序表

线性表的顺序储存结构是最简单、最常用的储存方式。顺序表是把线性表中所有的元素按照逻辑顺序依次储存到从计算机储存器中指定存储位置开始的一块连续的存储空间中而得到的线性表。因为内存中的地址空间是线性的,因此,用物理上的相邻实现数据元素之间的逻辑相邻关系简单方便。访问顺序表时,按位序访问每个元素花费的时间相等,均为O(n)。顺序表的储存类型定义如下:#define INIT_SIZE 10typedef struct SqList{ int *elem;//保存动态内存的地址 int l

2020-07-21 00:28:00 564

原创 make命令与Makefile文件简介

Make工程管理,就是管理工程项目中的几个文件。大家在平时的练习中,编译的文件个数一般不超过五个,即使有几个文件进行了更改,也只需要对其重新编译即可。但是工程若由成百上千个文件组成,而只有其中个别文件进行了修改,如果此时不知道哪几个文件被更改了,就只能用gcc把所有的文件重新编译一遍,这样大大降低了效率。所以Make工程管理器便应运而生了,它可以自动识别更新了的文件代码,只对更新的文件进行编译。这里的自动指的是能够根据文件时间戳自动发现哪个文件更新过。make工程管理器主要是通过一个叫Makefile的

2020-07-05 01:50:40 205

原创 Linux复习之静态库与动态库的区别

静态库在程序编译时会被链接到目标文件中,程序运行时不需要该库。缺点是编译后文件较大,但是隔离性好。动态库在编译时不会被链接到目标代码中,在程序运行时才被载入,所以程序运行时需要动态库存在。优点是编译后文件较小,多个应用程序可以使用同一个动态库,启动多个程序时,只需要将动态库加载到内存一次。通过之前的学习可以发现,在生成可执行文件时,无论使用动态库还是静态库,gcc命令的格式都是相同的,gcc main.c 库名。这时候生成的a.out文件并不能区别是静态库还是动态库。所以需要记住,当静态库和动态库同处于一

2020-07-02 02:34:01 190

原创 Linux复习之动态库的建立与使用

动态库又被称作共享库,编译时链接动态库,但是不加载目标代码,只有在运行时才加载相关的目标代码到内存,进程结束时自动释放所占内存。动态库的建立还是以排序函数sort.c与bank.h为例:1.编辑sort.c与bank.h文件2.生成sort.o文件指令:gcc -c -fpic sort.c选项-fpic的作用是将源文件编译成带有PIC标志的目标文件3.将文件加入到动态库中gcc -shared xxxxx.o yyyy.o -o libxxx.so动态库的使用和静态库一样,动态

2020-07-02 01:53:25 108

原创 Linux复习之静态库的使用

通常,可以通过两种方法来使用静态库。第一种,参数法;(不常用)格式:gcc 主程序 -l 静态库名(去掉lib和.a) -L 静态库存放位置第二种,直接法:gcc 主程序 静态库全名下面通过一个实例来展示静态库的使用方法:先建立bank.h与sort.c这两个文件,将sort.c生成目标文件并加入到静态库libmath.a中(可以翻看博文“静态库的建立”),当下,我们只需要编写源程序main.c,调用sortaz函数接下来,再对main.c进行编译时,应该把静态库libmath.a中的相关代

2020-07-01 02:18:20 309 1

原创 Linux复习之静态库的建立

库是在链接阶段和相应的.o文件生成可执行文件,根据链接方式的不同,可以分为静态库与动态库。当使用静态库时,连接器会找出程序所需的函数,将它们复制到执行文件中,因为是完整复制,所以一旦链接成功,可执行文件在静态库不存在的情况下依然可以执行。动态库与静态库不同,动态库会在程序内留下一个 标记,当程序执行时,指明必须载入的库文件,所以当执行文件时才动态加载库文件,使用动态库必然会节约空间。在linux下进行链接首先会链接动态库,也就是如果不特别指定,会默认链接动态库。静态库的建立1.先建立并编辑bank

2020-07-01 01:57:51 136

原创 Linux复习之gdb断点调试实例

断点就是指在程序的某一行设置一个点位,程序在这个指定的位置中断。在gdb调试下,设置断点的指令为break,通常有以下集中方式:break :在进入指定函数时停住break :在指定行号停住break +/-offset:在当前行号的前面或者后面的offset行停住offset为自然数break filename:linenum:在源文件filename的linenum行处停住break…if…:可以使上述的参数,condition表示条件,在条件成立时停住delete:删除所有断点delet

2020-06-30 02:06:58 1062

原创 Linux复习之gdb调试基本指令

初学者在编辑程序时,往往会出现很多的语法错误,这些错误在编译阶段就会暴露,所以很容易被排除,但是有些错误可能出现在程序运行阶段,需要深入的测试、调试和修改。这就使得在一些大型项目里,程序的调试变的十分困难,这个时候就需要一个高效的调试工具,gdb调试工具就是当前使用最广泛的的调试工具。gdb调试基本命令1.文件清单指令:list/l作用:列出产生执行文件的源代码的一部分例如:list 10 20作用是列出10到20行之间的代码list max作用是输出函数max前后的5行程序源代码、2.

2020-06-28 03:11:11 197

原创 Linux复习之gdb调试举例

源程序如下,作用是通过调用函数输出1~10的和:执行编译指令:gcc -o main main.c ,编译成功后,执行./main,程序显示结果result = 45程序可以顺利的编译链接生成可执行文件,说明没有出现编译问题,但是可以看见,输出结果为134518459,明显错误。正确结果应该是55,下面利用gdb对程序进行调试,从而找到问题。为了能够使用gdb调试,在由main.c编译链接生产可执行文件main时,命令行中必须加入选项-g。具体步骤如下:1.编译main.c,指令:gcc -o

2020-06-28 02:54:29 225

原创 C++复习之容器空间配置器allocator的实现

#include <iostream>using namespace std;//容器的空间配置器allocator//做四件事情:内存开辟与释放 对象构造与析构//定义容器的空间配置器,和C++标准库的allocator实现一样template<typename T>struct Allocator{ T* allocate(size_t size)//负责内存开辟 { return (T*)malloc(sizeof(T) *

2020-06-18 02:56:16 152

原创 Linux复习之gcc 编译多文件

在实际的项目中,为了使代码结构更加合理,往往将主函数和其他函数放在不同的源文件中,除了主函数外,每个函数都有函数声明和函数实现两个部分。函数的声明、宏定义、自定义类型、类型别名等内容通常放在头文件(.h)里,函数的实现放在.c文件中。实例演示:1、使用vim创建test.c文件,文件内代码如下2、使用vim创建m.c,里面包含max函数的实现方法3、使用vim创建头文件bank.h,里面包含max函数的声明4、多个文件一起编译指令:gcc test.c m.c -o test将多个源文

2020-06-09 03:36:33 641

原创 Linux复习之gcc编译工具

初识gccgcc是“GNU Compiler Collection”的缩写,是一个编译器集合。在Linux操作系统下,gcc编译器是最常见的一种编译器,它不仅仅可以用来编译C语言,还可以用来编译C++、Java、等语言。gcc的语法格式:gcc [选项] 参数gcc命令的主要选项:[-o]:指定目标文件的名称[-g]:使生成的可执行程序中包含debug信息[-c]:只编译不链接[-E]:只做预处理[-S]:由C编译成汇编省略选项是最简单的gcc使用方式。实例:1.使用vim建立一个“m

2020-06-08 04:16:33 230

原创 Linux复习之vim(文本编辑器)

vim编辑器只能编辑字符,不能向Windows中的文字处理软件Word等对文字进行排版工作。vim可以执行输出、删除、查询、替换等多数文本操作,而且用户可以根据需要对其进行定制。vim共有3中工作模式:命令模式、插入模式和末行模式。1、命令模式当使用vim创建或打开一个文件时,默认的模式就是命令行模式。在此模式下输入的字符都会作为命令来解析。命令模式进入插入模式的指令:a:从当前光标位置之后插入i:从当前光标位置开始插入o:下一行开始插入O:上一行开始插入cc:整行删掉后插入C:删除光标

2020-06-03 02:57:37 289

原创 Linux复习之硬链接与软链接

在Linux系统中文件被分为两个部分:用户数据(user data)与元数据(meta data)。用户数据,即文件数据块(data block),数据块是记录文件真实内容的地方。元数据,则是文件的附加属性,如文件大小、创建时间、所有者信息者。在Linux系统中,元数据中的inode号(即索引节点好)才是文件中唯一的标识而不是文件名。系统通过inode号寻找正确的文件数据块。为了解决文件的共享使用问题,Linux引入了两种链接:硬链接(hard link)与软链接(又称符号链接,即soft link

2020-06-03 02:23:20 197

原创 Linux复习之深入了解shell

一、通配符通配符的作用是同时匹配多个文件以便于操作。常用的通配符是“*”和“?”,除此之外,还包括由[]-!组成的模式。例如:cp *.c/home:将当前目录下所有.c文件复制到/home文件夹中rm-f a?d.txt:强制删除当前目录下首字符是a、尾字符是d的文件二、重定向重定向,就是重新定向的意思。在Linux操作系统中,标准输入设备是键盘,标准输出设备是显示器。与输入有关的只有输入重定向,与输出有关的重定向分为输出重定向、附加输出重定向和错误输出重定向。(1)输入重定向(0<

2020-06-01 17:55:00 195

原创 Linux复习之gcc软件包的安装

Linux下翻译工具gcc的安装1.切换到root用户指令:su root2.在/mnt 下创建一个新的目录指令: cd /mnt --> mkdir dvd3.挂载镜像指令:mount /dev/cdrom /mnt/dvd4.修改yum的配置文件指令:cd /etc/yum.repos.d添加代码:vim yum.repo[serid]Name=stuBaseurl=file:///mnt/dvdgpgcheck=05.验证挂载是否正确指令:Y

2020-06-01 03:54:15 679

原创 Linux复习之初识shell常用命令②

文件的归档与压缩在Linux操作系统中,使用tar命令可以为文件和目录创建备份。使用tar命令,用户可以为某一特点文件创建备份文件,也可以在备份中改变文件,或者向备份文件中加入新的文件。使用tar命令,可以把大量文件和目录全部打包成一个文件,或者将备份文件和几个文件合并成一个文件,以便于网络传输。tar命令详解:使用格式:tar[主选项 + 辅助选项] + 文件或者目录主选项主要告诉tar要做的事情,辅助选项可以选用选项说明:[c]:创建打包备份文件[r]:追加到备份文件的末尾。当用户做好备份

2020-06-01 03:49:32 140

原创 Linux复习之初识shell常用命令①

目录与文件操作命令1、pwd命令使用格式:pwd作用:显示当前目录的绝对路径Linux中的路径分为相对路径和绝对路径,绝对路径是指从根目录/出发到当前目录或者文件的路径,而相对路径是指从当前目录到其下子目录或文件的路径。目录之间用“/”分隔。2、cd命令使用格式:cd + [目录相对路径或者绝对路径]作用:切换到指定目录3、ls命令使用格式:ls + [选项] + [文件或者目录]作用:无任何选项的情况下,参数若是目录,显示当前目录下的文件以及子目录信息;如果参数是文件,则显示

2020-05-29 05:09:57 451

空空如也

空空如也

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

TA关注的人

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