- 博客(108)
- 收藏
- 关注
原创 STL的allocaotr
allocator类是C++的一个模板,它提供类型化的内存分配以及对象的分配和撤销。allocator称为分配器(空间配置器)STL的分配器用于封装STL容器在内存管理上的底层细节。在C++中,其内存配置和释放如下:new运算分两个阶段:(1)调用::operator new配置内存;(2)调用对象构造函数构造对象内容delete运算分两个阶段:(1)调用对象希构函数;(2)掉员工::op...
2020-03-02 20:37:32
935
原创 C++ 静态函数与虚函数的区别
经常在网上看到大家在讨论静态函数与虚函数的区别,往往可以看到统一的答案是:静态函数在编译的时候就已经确定运行时机,虚函数在运行的时候动态绑定。虚函数因为用了虚函数表机制,调用的时候会增加一次内存开销。这个答案是正确的,但是一般不懂得虚函数表原理的人,看了可能也是一头头雾水。下面我们就先来说说什么是虚函数表:虚函数表: 当一个类中包含被virtual 关键字修饰的成员函数时,该成员函数就成为了一...
2020-03-02 19:57:51
4181
2
原创 NAT技术 与NAPT技术 、 NAT穿越
首先了解以下两个概念:公有IP地址:也叫全局地址,是指合法的IP地址,它是由NIC(网络信息中心)或者ISP(网络服务提供商)分配的地址,对外代表一个或多个内部局部地址,是全球统一的可寻址的地址。私有IP地址:也叫内部地址,属于非注册地址,专门为组织机构内部使用。因特网分配编号委员会(IANA)保留了3块IP地址做为私有IP地址:10.0.0.0 ——— 10.255.255.255172...
2019-11-14 20:53:06
710
2
原创 简单的进度条程序 ------行缓冲区概念,/r与/n的区别
先来了解以下:/r 与 /n 的区别:’\r’是回车,前者使光标到行首,(carriage return)'\n’是换行,后者使光标下移一格,(line feed)\r 是回车,return\n 是换行,newline行缓冲区概念行缓冲:在I/O操作时,输入输出遇到换行符时进行,进行真正的I/O操作。对于行缓冲,标准I/O每一行缓冲区的长度是固定的,所以只要填满了缓冲区,即...
2019-10-22 19:07:16
937
1
原创 学习笔记 ----liunx gcc(动静态链接,debug/release版本编译)、gdb(基础调试系列指令)、makefile/make(依赖关系,依赖方法及相关问题)、使用详解。
个人的某天学习笔记、以下都是满满的干货:简单命令:rm删除以sum开头的文件 rm sum 这里的‘*’ 称为通配符。*gcc的使用细节gcc 默认连接方式 ---->动态链接,release版本(不支持调试)生成debug版本可执行: gcc test.c -o test -g以静态链接的方式生成 :gcc test.c -o test -static编译时去掉...
2019-10-22 18:13:18
404
1
原创 定位new表达式 、内存泄漏、相关问题(如何一次在堆上申请4G的空间?分别设计量个类,一个只能在堆上创建对象,一个只能在栈上创建对象)
定位new表达式定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。使用格式:new (place_address) type或者new (place_address) type(initializer-list)place_address必须是一个指针,initializer-list是类型的初始化列表(无参数是时可省略)使用场景:定位new表达式在实际中一般是配合...
2019-10-20 16:36:10
374
原创 malloc/free和 new/delete 的区别
malloc/free和new/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同之处有很多:malloc和free是函数,new和delete是操作符malloc申请的空间不会初始化,new可以初始化malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后...
2019-10-20 15:41:50
176
原创 单例模式 -----------《饿汉模式、懒汉模式》 原理,缺陷及改进方法
设计模式:什么是设计模式?设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。今天我们要看的是设计模式的一种“单例模式”单例模式一个类只能创建一个对象,即单例模式。该模式可以保...
2019-10-20 15:34:05
1054
原创 C++11特性《 右值引用-<完美转发>、lambda表达式》
1.右值引用1.1移动语义如果一个类中涉及到资源管理,用户必须显式提供拷贝构造、赋值运算符重载以及析构函数,否则编译器将 会自动生成一个默认的,如果遇到拷贝对象或者对象之间相互赋值,就会出错,比如:class String{ pulic: String(char* str) { if(str == nullptr) str = ""; _str = new c...
2019-10-19 18:10:27
1034
原创 C++11部分新特性一、《 范围for、变量类型推导、初始化列表、 委派构造函数、默认函数控制 》
1.初始化列表2.1 C++98中{}的初始化问题在C++98中,标准允许使用花括号{}对数组元素进行统一的列表初始值设定。比如:int array1[] = {1,2,3,4,5}; int array2[5] = {0};对于一些自定义的类型,却无法使用这样的初始化。比如:vector<int> v{1,2,3,4,5};就无法通过编译,导致每次定义vector时...
2019-10-19 15:08:27
351
原创 C++ 强制类型转换 reinterpret_cast、static_cast、const_cast、dynamic_cast ----关键字 explicit 的用法
C++ 为什么要有强制类型转换?C语言中很多类型的转换都是1.C语言的类型转换void Test(){ int i = 1; //隐士类型转换 double d = i; printf("%d ,%.2f\n",i,d); int* p = &i; //显示的强制类型转换 int address = (int) p; printf("%x,%d\n"...
2019-10-18 18:57:27
362
原创 RAII的扩展学习 简单的守卫锁----防止死锁
RAII思想除了可以用来设计智能指针,还可以用来设计守卫锁,防止异常安全导致的死锁问题。下面就简单实现一个守卫锁:先来看代码:#include<thread>#include<mutex>tempalte<class Mutex >class LockGuard{ public: LockGuard(Mutex& mtx) :_...
2019-10-18 16:21:08
389
原创 RAII ------- 智能指针-----------auto_ptr、unique_ptr、shared_ptr 的使用原理、模拟实现、以及缺陷
1.为什么需要智能指针?C++中异常经常会导致资源泄漏的问题,比如在new和delete中抛出了异常,导致内存泄漏,在lock和 unlock之间抛出了异常导致死锁。为了解决这些情况,我们通常使用RII来解决。2.智能指针的使用及原理2.1 RAIIRAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源(如内存、文件句 ...
2019-10-18 16:00:25
329
原创 C++ 异常
1.C语言传统处理错误的方式传统的错误处理机制:终止程序**,如assert,**缺陷:用户难以接受。如发生内存错误,除0错误时就会终止程序。返回错误码,缺陷:需要程序员自己去查找对应的错误。如系统的很多库的接口函数都是通过把错误码 放到errno中,表示错误。C 标准库中setjmp和longjmp组合。这个不是很常用,了解一下 。实际中C语言基本都是使用返回错误码的方式处理错误...
2019-10-15 19:57:30
658
原创 C++ 继承
1.继承的概念及定义1.1 继承的概念继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特 性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用。1.2 继承的定义1.2.1 继承的格式下面我们看到B是父类...
2019-10-15 16:19:00
206
原创 容器适配器 -------------- stack 、queue、priority_queue的使用以及 为什么默认使用deque作为底层容器?
什么是适配器?适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。1.为什么将stack、queue和priority_queue称作为容器适配器?虽然stack、queue、priority_queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将 其称为容器适配器,这...
2019-10-11 16:09:38
902
1
原创 布隆过滤器 ---- 实现以及性能分析
我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,它每次推荐时要去重,去掉那些已经看 过的内容。问题来了,新闻客户端推荐系统如何实现推送去重的? 用服务器记录了用户看过的所有历史记 录,当推荐系统推荐新闻时会从每个用户的历史记录里进行筛选,过滤掉那些已经存在的记录。 如何快速查 找呢?1. 用哈希表存储用户记录,缺点:浪费空间。2. 用位图存储用户记录,缺点:不能处理哈希冲突。3....
2019-10-05 17:37:16
2352
原创 位图 ---- 应用以及实现
如果给你40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中?遍历,时间复杂度O(N)排序(O(NlogN)),利用二分查找: logN位图解决 数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,为0代表不存在。比如:1.位图的概念所谓位图,就...
2019-10-05 16:47:05
473
原创 哈希 ---《哈希函数》------除数的选取为什么是质数?、《哈希冲突》------解决方法、《闭散列》、《开散列》
一、哈希概念顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关系,因此在查找一个元素时,必须要经过关键码的多次比较**。顺序查找时间复杂度为O(N),平衡树中为树的高度,即O(logN )**,搜索的效率取决 于搜索过程中元素的比较次数。理想的搜索方法:可以不经过任何比较,一次直接从表中得到要搜索的元素。 如果构造一种存储结构,通过 某种函数(hashFunc)使元素的存储位置与它的...
2019-10-03 17:52:16
4310
原创 哈希切割 ------ TOP K问题
题目:给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址? 与上题条件相同, 如何找到top K的IP?1.找出出现次数最多的IP地址最易想到的方法就是去遍历这个文件:使用嵌套的循环去统计每个IP地址出现的次数,最终找出出现次数最多的。这种方法可行,但有很大缺陷:首先100G的文件不可能一次性加载到内存,因此就需要对文件进行分割,而统计每...
2019-10-02 13:43:59
641
1
原创 AVL树的实现
1.AVL树的概念二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当 于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年 发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之 差的绝对值不超过1(需要对树中的结点进行调整),即可降低树...
2019-09-25 23:16:44
846
原创 二叉搜索树
二叉搜索树一、二叉搜索树概念二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:若它的左子树不为空,则左子树上所有节点的值都小于根节点的值若它的右子树不为空,则右子树上所有节点的值都大于根节点的值它的左右子树也分别为二叉搜索树例如下图为一个二叉搜索树:二、二叉搜索树操作1.二叉搜索树的查找插入的具体过程如下:设查找的值为a ;从根节点开始,若根节点...
2019-09-25 13:37:28
1374
原创 四、归并排序、非比较排序 (归并排序、计数排序)
一、归并排序基本思想:归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有 序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。 归并排序核心步骤:看下图:归并排序实现代码如下:#include<stdi...
2019-09-11 17:14:32
198
原创 三、 交换排序 (冒泡排序,快速排序---《hoare版本快排》、挖坑法、前后指针法)
交换排序基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。1.冒泡排序void BubbleSort(int* a,int n){ for(int i=0;i<n-1;i++) { for(int j=0;j<n-1-i;j++) //注意边界为...
2019-09-11 15:41:48
321
原创 一、排序 ----- 插入排序(直接插入排序、希尔排序)
1.排序的概念及其运用1.1排序的概排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排 序算法是稳定的;否则称为不稳定的。内部...
2019-09-10 22:29:02
210
原创 C语言 队列的接口实现
1.队列的概念队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头。2.队列的实现队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数 组头上出数据,效率会比较低。队列实现代码如下:...
2019-09-09 22:32:41
359
原创 C语言 栈的接口实现
栈的概念栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。出栈:栈的删除操作叫做出栈。出数据也在栈顶。话不多说了解了栈的特点以后,直接看实现代码://Stack.h//栈的相关接口的...
2019-09-09 22:12:59
460
原创 链表--- 双向链表及其实现
双向带头链表双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。实现代码如下:无头双向循环链表:接口:#include<stdio.h>#include<stdlib.h>#include<assert....
2019-09-09 21:49:19
314
原创 链表 ---单向链表
讨论单链表之前,我们先来讨论下面这个问题。顺序表存在的一些问题:中间/头部的插入删除,时间复杂度为O(N)增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200, 我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。为了解决顺序表存在的这些问题,我们就要学习另外一种数据...
2019-09-09 21:12:05
595
原创 C语言 关键字static的用法
关键字static在C语言中: static是用来修饰变量和函数的修饰局部变量修饰全局变量修饰函数1.修饰局部变量看下面两段代码://代码1#include<stdio.h>void test(){ int i=0; i++; printf("%d ",i);}int main(){ for(int i=0;i<10;i++) { te...
2019-09-06 17:38:24
257
转载 编译 与 链接 详解
编译与链接过程详解C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接。编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程。链接是把目标文件、操作系统的启动代码和用到的库文件进行组织形成最终生成可执行代码的过程从图上可以看到,整个代码的编译过程分为编译和链接两个过程,编译对应图中的大括号括起的部分,其余则为链接过程。过程...
2019-09-06 16:42:41
3393
原创 位段、联合体(共用体)详解、枚举 -------- 用共用体判断大小端
一、位段1.什么是位段?有些数据在存储时并不需要占用一个完整的字节,只需要占用一个或几个二进制位即可。例如开关只有通电和断电两种状态,用 0 和 1 表示足以,也就是用一个二进位。正是基于这种考虑,C语言又提供了一种叫做位域的数据结构。位段的声明和结构是类似的,有两个不同:.位段的成员必须是 int、unsigned int 或signed int 。位段的成员名后边有一个冒号和一个数...
2019-09-06 09:37:52
1481
原创 结构体内存对齐详解
我们已经掌握了结构体的基本使用了。 现在我们深入讨论一个问题:计算结构体的大小。内存对齐先来讨论这个问题:为什么存在内存对齐?大部分的参考资料都是如是说的:平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址 处取某些特定类型的数据,否则抛出硬件异常。性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐...
2019-09-05 10:45:15
870
原创 atoi 与 itoa的用法
atoi头文件:#include<stdlib.h>函数声明: *int atoi(const char str)功能: 把参数 str 所指向的字符串转换为一个整数(类型为 int 型)。参数:str --要转换为整数的字符串。返回值:该函数返回转换后的长整数,如果没有执行有效的转换,则返回零。使用举例:#include<stdio.h>#include...
2019-09-05 08:51:53
625
原创 memcpy 函数、 memmove函数用法及模拟实现
一、memcpy 内存拷贝函数函数描述:void * memcpy ( void * destination, const void * source, size_t num )功能: 从存储区 source复制 n 个字符到存储区 destination。参数:destination-- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。source-- 指向要复制的...
2019-09-04 16:21:43
281
原创 常见库函数 strcpy,strlen,strcmp,strstr ,strcat的用法及模拟实现
常见库函数1.strcpy字符串复制函数头文件:#include<string.h>函数原型char * strcpy(char * strDest,const char * strSrc);该函数功能是将后面字符串的内容复制给前面的字符串。源字符串 即后面的字符串保持不变,前面的字符串被改变。看下面的代码:#include<stdio.h>#includ...
2019-09-03 23:34:48
797
原创 函数指针 、函数指针数组 、函数指针数组的指针
在指针的学习过程中有这么几种指针在定义是经常会让我们犯错:函数指针、函数指针数组、函数指针数组的指针。下面我们逐个了解这几种指针。一、 函数指针函数指针顾名思义:指向函数的指针。我们知道整型、浮点型、字符型指针存放的都是其对应变量的存储地址,那么很容易可以理解,函数指针存放的就是函数的地址。函数的地址是什么呢? 我们看下面的代码:void test(){ printf("hello ...
2019-09-03 20:42:38
201
原创 C语言 指针与数组的区别与联系
什么是数组:数组是用于存放多个相同类型数据的集合。什么是指针:指针是一个变量,但是与其他变量不同,指针存放的是其他变量在内存中的地址。下面我们谈谈指针与数组的不同:1.赋值同类型的指针变量可以相互赋值,数组不可以,只能一个一个的赋值。2.存储方式数组:数组在内存中是连续存放的,开辟一块连续的内存空间。数组是根据数组的下进行访问的,多维数组在内存中是按照一维数组存储的,只是在逻辑上是...
2019-09-03 19:35:07
479
原创 C语言 浅谈《数据存储》
学习C语言的我们知道,数据的创建是在内存中开辟空间的。数据类型的不同,对应开辟出来的存储空间的大小也会有所不同,那么数据在内存中具体是怎么进行存储的呢?正反补码在32位的系统中,一个int是四字节,数据在内存中以补码的形式存储的。正数的补码就是它本身负数的补码等于它取反加1如上图所示:正整数a在内存中的存储地址为0X00C7FBB4 存储格式为03 00 00 00负整数b在内...
2019-09-02 14:31:06
203
原创 Linux 基础指令
1. ls指令语法: ls [选项][目录或文件]功能:对于目录,该命令列出该目录下的所有子目录与文件。对于文件,将列出文件名以及其他信息。常用选项:-a 列出目录下的所有文件,包括以 . 开头的隐含文件。-d 将目录象文件一样显示,而不是显示其下的文件。 如:ls –d 指定目录-i 输出文件的 i 节点的索引信息。 如 ls –ai 指定文件-k 以 k 字节的形式表示文件的大小...
2019-08-06 17:59:51
473
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅