![](https://img-blog.csdnimg.cn/20201014180756738.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
C/C++
Wzning0421
I'm always learning.
展开
-
Linux c++ udp按包发送接收文件
我最近写一个项目的时候需要涉及到udp传输文件.网上找了找发现没什么合适的,那么我就写了一个自己的供参考.文件分成两类:第一类是文本文件,第二类是二进制文件.他们的文件读写是不一样的.所以我提供了两种文件的读写,传输方式.首先看源端DataSource的main.cpp:#include "UDPSocket.h"#include "Package.h"#include <unordered_map>#include <iostream>#include &l原创 2021-01-03 22:52:55 · 2411 阅读 · 5 评论 -
String类的实现
#include <iostream>#include <cstring>using namespace std;class String{public: // 默认构造函数 String(const char *str = nullptr); // 拷贝构造函数 String(const String &str); // 析构函数 ~String(); // 字符串赋值函数 String&.原创 2020-09-03 13:38:21 · 455 阅读 · 0 评论 -
C++ 实现一个简单内存池
在使用内存池进行内存管理之前,通常使用new/malloc或者delete/free来申请或者释放内存。在这个过程中,系统要首先查找内部维护的内存空闲块表,并且需要根据比如LRU等内存分配算法找到合适大小的空闲内存块。如果该空闲内存块过大,还需要切割成已分配的部分和较小的空闲块。然后系统更新内存空闲块表,完成一次内存分配。类似地,在释放内存时,系统把释放的内存块重新加入到空闲内存块表中。如果有可能的话,可以把相邻的空闲块合并成较大的空闲块。默认的内存管理函数还考虑到多线程的应用,需要在每次分配和释放内存时加原创 2020-08-09 18:17:14 · 800 阅读 · 0 评论 -
C++ 泛型编程
泛型编程就是独立于确定的类型的方式编写代码,需要提供具体程序实例所操作的类型或者值,而不是之前确定的。比如在stl容器中,vector<int>, vector<char> vector<double> 用的是不同的数据类型,但是声明和调用的语句却是一样的。这就是泛型--建立通用的模具以提高复用性。 泛型的一个关键就是模板。通过template关键字来声明使用模板,通过typename来定义模板使用的是哪种类型。基本的模板有两种:函数模板...原创 2020-06-28 16:50:30 · 494 阅读 · 0 评论 -
C++11常见新特性
1. auto关键字auto关键字起到的作用是自动类型判断。在声明变量的时候根据左值可以判断出类型并自动为此变量选择相匹配的类型。比如:#include <iostream>#include <string>#include <queue>#include <vector>#include <map>#include ...原创 2020-04-28 16:13:23 · 171 阅读 · 0 评论 -
C++11新特性 右值引用与移动语义
右值引用作用是可以减少内存拷贝次数,从而优化性能。 首先,什么是右值?右值是一个与左值相区分的概念。左值是:既能出现在等号左边也能出现在等号右边的变量或表达式,比如int a = 5,那么a就是一个左值,因为它可以出现在等号左边被赋值,也可以在等号右边给别人赋值。右值:因为声明结束后会被销毁,所以不能放在等号左边,比如上面int a = 5;这句话的5,就是一个明...原创 2020-04-25 23:30:29 · 472 阅读 · 0 评论 -
C++11新特性之 可变参数模板
C++ 11的可变模版参数是其新增的最强大的特性之一。通过对参数进行了泛化,可以表示从0到任意个数、任意类型的参数。我们知道对于一个模板类来说,通常只能含固定数量的模版参数,可变模版参数无疑是一个巨大的改进。下面来具体说一下:可变参数模板与通常的类模板写法相似。声明可变参数模板时需要在typename后面带上省略号 ... 。写法如下:template<typename T, ty...原创 2020-04-25 18:04:28 · 754 阅读 · 0 评论 -
C++ 自己实现一个unordered_map(hashmap)
今天面试的时候遇到面试官出了一个问题,要实现一个unordered_map. 我实现的不太好,所以面试之后重新自己整理实现了一个unordered_map,在此记录一下。首先unordered_map的底层实现是哈希表。那么对于任何一个关键key的哈希,首先需要考虑的是哈希冲突的问题,在这里应该用链表的方式解决。如果不同的key哈希成了同一个地址,那么在链表的基础上向后连接就行。然后主要实现的...原创 2020-04-25 13:55:29 · 2249 阅读 · 1 评论 -
用模板类实现shared_ptr和unique_ptr
今天面试的时候被问到了一个问题,要我用模板类实现一个shared_ptr. 坦白来说这道题我并不会做,因为我对于shared_ptr的认知仅仅停留在引用计数上面。所以查阅了资料写了一份代码出来,希望对于更深入理解共享智能指针有帮助吧。首先就是每个指针类应该有一个引用计数变量,以及一个模板指针,用于存放对应的不同类型的指针。对于shared_ptr来说,指针指向相同的位置,引用计数要加1. 同时...原创 2020-04-12 18:06:47 · 387 阅读 · 0 评论 -
C++11 智能指针
c++里面支持四种智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr。 其中后三个是c++11支持,并且第一个已经被c++11弃用。为什么要用智能指针呢?因为c++的内存管理是需要手动管理的,当new一个对象的时候,一般就会立即把delete语句直接也写了,但是我们不能避免程序还未执行到delete时就跳转了或者在函数中没有执行到最后的delete语句...转载 2020-03-27 12:18:04 · 195 阅读 · 0 评论 -
malloc,free 与new delete的区别
1 malloc与freeC语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。2对于非内部数据(比如int char*这种)类型的对象而言,光用maloc/free无法满足动态对象的要求,这是因为对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构...原创 2020-03-26 23:04:10 · 118 阅读 · 0 评论 -
stl vector 容量与大小之间的关系
当对vector进行push_back等操作的时候,当超出之前内存所分配的部分之后,需要新增内存空间存放更多元素。将原来的数据复制过来,释放之前的内存,然后插入新增加的元素;那么这个过程是怎么样的呢?我们用代码来试一下:VS2013环境下如下:#include<iostream>#include<vector>using namespace std;int ...原创 2020-03-24 17:47:36 · 605 阅读 · 0 评论 -
面向对象的程序设计特点
面向对象的程序设计特点主要有四个:抽象、封装、继承、多态。1. 抽象:首先在面向对象的程序设计中,每一种事物都可以成为“对象”。那么一个对象可以有多个特点,比如人有身高,体重等等。把一个事物对象的特点概括表示出来的过程叫做抽象。比如员工对象的薪水,上班时间,绩效考考核等等。2. 封装:在完成抽象之后,把静态属性和动态属性归为一个整体,那么这个步骤叫做封装。通过封装,一个对象的属性和操作这些...原创 2020-02-25 22:55:56 · 8358 阅读 · 0 评论 -
c++ 数据结构之 线段树
线段树是一种数据结构,是一种二叉树。线段树将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。线段树对于区间求和等区间操作能够实现复杂度为O(logn)的操作,故得以广泛利用。修改一个值的操作也是O(logn)。 线段树是建立在线段基础上,每个结点都代表了一条线段[a,b]。长度为1的线段称为元线段。非元线段都有两个子结点,左结点代表的线段为[a,...原创 2020-02-17 20:12:59 · 1694 阅读 · 0 评论 -
函数指针以及在类成员函数中应用函数指针
什么是函数指针如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名表示的就是这个地址。既然是地址我们就可以定义一个指针变量来存放,这个指针变量就叫作函数指针变量,简称函数指针。那么这个指针变量怎么定义呢?虽然同样是指向一个地址,但指向函数的指针变量同我们之前讲的指向变量的指针变量的定义方式是不同的。例如:in...原创 2019-10-31 22:46:26 · 534 阅读 · 0 评论 -
函数宏定义 与函数自定义
为什么在C语言中要有函数宏定义这种形式呢?宏定义可以帮助我们防止出错,提高代码的可移植性和可读性等。 在软件开发过程中,经常有一些常用或者通用的功能或者代码段,这些功能既可以写成函数,也可以封装成为宏定义。那么究竟是用函数好,还是宏定义好?这就要求我们对二者进行合理的取舍。 我们来看一个例子,比较两个数或者表达式大小,首先我们把它写成宏定义: #define MAX( ...原创 2019-10-06 23:04:26 · 1931 阅读 · 0 评论 -
C++中对象初始化赋值是否需要调用operator=函数
一般对于初始化类变量有两种方式:A a;A b = a;另一种方式是:A a ;A b;a =b;对于第一种方式,编译器相当于在b的初始化的时候,用a的引用作为复制构造函数的参数进行操作,相当于A b(a);而对于第二种方式,则应该是用了赋值构造函数,也就是=的重载。因为a和b本身都已经重载了,就相当于把b的值赋给a了。比如代码如下:class mytest{...原创 2019-09-25 20:29:43 · 322 阅读 · 0 评论 -
腾讯校园招聘笔试 2019-8-17 第三题
小Q在进行一场竞技游戏,这场游戏的胜负关键就在于能够能争夺一条长度为L的河道,即可以看作是[0,L]的一条数轴。这款竞技游戏当中有n个可以提供视野的道具-真视守卫,第i个真视守卫能够覆盖区间[xi,yi]。现在小Q想知道至少用几个真视守卫就可以覆盖整段河道。输入:输入包括n+1行。第一行包括两个整数n和L(1<=n<=10^5,1<=L<=10^9)接下...原创 2019-08-18 15:51:25 · 1675 阅读 · 1 评论 -
排序算法之 堆排序
堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。什么是完全二叉树呢?可以看下这篇文章:https://blog.csdn.net/hanzhen7541/article/details/99437854所以说,堆排序是将数组当做完全二叉树、根据完全二叉树的特性来...原创 2019-08-16 17:16:54 · 219 阅读 · 0 评论 -
C++ 中的volatile关键字解析
volatile 关键字是一种类型修饰符,和 const 对应,用来修饰变量。用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读...原创 2019-08-06 14:19:13 · 1299 阅读 · 0 评论 -
C++ 基类和派生类的virtual虚析构函数
virtual虚函数与C++的多态息息相关,C++中基类采用virtual虚析构函数主要目的是为了防止潜在的内存泄漏。具体地说,如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存...原创 2019-08-06 14:28:32 · 2440 阅读 · 0 评论 -
腾讯校园招聘笔试 2019-8-17 第四题
小Q在周末的时候和他的小伙伴来到大城市逛街,一条步行街上有很多高楼,共有n座高楼排成一行。小Q从第一栋一直走到了最后一栋,小Q从来没有看到过这么多高楼,所以他想知道他在每栋楼的位置处能看到多少栋楼呢?(当前面的楼的高度大于等于后面的楼时,后面的楼将被挡住)输入描述:输入第一行将包含一个数字n,表示楼的栋数,接下来的一行将包含n个数字wi(1<=i<=n),代表一栋楼的高度。...原创 2019-08-18 23:06:43 · 3115 阅读 · 4 评论 -
为什么C++构造函数不能是虚函数
这是一个“鸡生蛋还是蛋生鸡”的问题。首先我们要明白,虚函数是如何调用的。如果一个类有虚函数,那么必然对应一个虚函数表vtable,这个虚函数表的指针指向的是虚函数的地址。当一个基类指针想要调用派生类的虚函数的时候,需要通过这个虚函数表来查找调用这个派生类的虚函数。那么,既然知道了虚函数是如何调用的,那么虚函数表是什么时候形成的呢?它是构造函数初始化示例的时候进行初始化的,也就是说构造函数初...原创 2019-08-07 13:25:19 · 863 阅读 · 0 评论 -
为什么静态static成员函数不能成为virtual虚函数
首先什么是static静态成员函数?静态成员函数不属于类中的任何一个对象和实例,属于类共有的一个函数。也就是说,它不能用this指针来访问,因为this指针指向的是每一个对象和实例。对于virtual虚函数,它的调用恰恰使用this指针。在有虚函数的类实例中,this指针调用vptr指针,指向的是vtable(虚函数列表),通过虚函数列表找到需要调用的虚函数的地址。总体来说虚函数的调用关系是:...原创 2019-08-07 13:35:43 · 2699 阅读 · 1 评论 -
为什么C++静态static函数不能访问非静态成员
原因如下:1. 静态static成员函数不同于非静态函数,它只属于类本身,而不属于每一个对象实例。静态函数随着类的加载而独立存在。与之相反的是非静态成员,他们当且仅当实例化对象之后才存在。也就是说,静态成员函数产生在前,非静态成员函数产生在后,不可能让静态函数去访问一个不存在的东西。2. 在访问非静态变量的时候,用的是this指针;而static静态函数没有this指针,所以静态函数也确实...原创 2019-08-07 13:48:46 · 3519 阅读 · 2 评论 -
upper_bound( )和lower_bound()的用法
lower_bound( )和upper_bound( )都是在排好序的数组中使用的。他们利用二分查找,以O(logn)的时间复杂度返回一个符合条件的索引值。下面进行解析:非重载的lower_bound( )和upper_bound( )用于在从小到大的排序数组中的查找:lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等...原创 2019-08-19 13:58:55 · 280 阅读 · 0 评论 -
初始化列表和构造函数内赋值的区别
1. 类的静态成员变量不能用参数初始化表初始化(1) 如果声明了类而未定义对象,则类的一般数据成员是不占内存空间的,只有在定义对象时,在运行的时候才为对象的数据成员分配空间。但是静态数据成员不属于某一个对象,在为对象所分配的空间中不包括静态数据成员所占的空间。静态数据成员是在所有对象之外单独开辟空间,也就是在静态变量区。只要在类中指定了静态数据成员,即使不定义对象,也为静态数据成员分配空间,...原创 2019-08-10 14:22:17 · 3680 阅读 · 0 评论 -
C++类成员的初始化顺序
C++中变量的初始化顺序应该是:1 基类的静态变量或全局变量 2 派生类的静态变量或全局变量 3 基类的成员变量 4 派生类的成员变量注意,对于一个类中的变量,初始化的顺序并不是按照初始化成员列表的顺序进行初始化,而是根据类中变量定义的顺序来初始化的。比如:下面一个例子输出应该是多少?class A{private: int n1; int n2; ...原创 2019-08-10 14:46:48 · 3235 阅读 · 0 评论 -
C++中定义和声明的区别
一个C++程序可能由许多文件构成,为了让多个文件访问相同的变量,C++区分了声明和定义。变量的定义(definition)用于为变量分配存储空间,还可以为变量指定初始值。在程序中,变量有且仅有一个定义。声明(declaration)用于向程序表明变量的类型和名字。定义也是声明:当定义变量的时候我们声明了它的类型和名字。可以通过使用exte...原创 2019-08-10 21:42:01 · 419 阅读 · 0 评论 -
C++ 引用以及和指针的区别
所谓引用,通俗来说就是一个对于一个变量起得“别名”。引用的声明是: 类型标识 & 引用变量名称 = 被引用变量名。应该注意:(1)声明引用时,必须同时对其进行初始化,这里面&不是取地址,而是声明被引用变量有一个别名。(2)引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量名的别名。 b=1; 等价于 a=1;(3)声明一个...原创 2019-08-11 13:15:26 · 93 阅读 · 0 评论 -
c/c++ 内存对齐
话说今天写程序,遇到一个问题:class TreeNode { char c; int val; TreeNode(){} virtual ~TreeNode(){}};这个TreeNode类的大小是多少呢?我最开始一位是1+4+4(虚函数表指针),但是实际一输出是12.这是为什么呢?这就涉及到C语言中内存对齐的概念了。为什么要进行内存对齐呢?CP...原创 2019-08-11 14:04:00 · 359 阅读 · 0 评论 -
二分查找 递归与非递归实现
二分查找将一个有序数组查找的时间复杂度从O(n)降到了O(logn). 首先是最基本的二分查找:public int binarySearch(int[] arr, int target, int n){//n是数组总长度 int low = 0, high = n-1, mid; while(low <= high){ mid = low + (hig...原创 2019-08-15 14:12:40 · 226 阅读 · 0 评论 -
c++排序算法之 快速排序
快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序的序列。 复杂度分析:快速排序在最理想的情况下复杂度是O(nlogn),在最差的情况下是O(n^2)....原创 2019-08-15 20:54:15 · 162 阅读 · 0 评论 -
排序算法之 归并排序
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法。 该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。具体而言,是让每个小的子序列都有序,然后有序的合并这些子序列,从而得到一个整体有序的序列。对于归并排序,其时间复杂度是O(nlogn).因为每次都将其对半分,...原创 2019-08-15 21:55:21 · 126 阅读 · 0 评论 -
排序算法之 插入排序
所谓插入排序,是一种简单而稳定的排序方法。基本思想是:将序列分成有序组和无序组。每次从无序组中选择一个,以插入的形式放进有序组。知道无序组的数字被抽光,所得到的有序组就是最终的排序结果。代码实现如下:void insert_sort(int *array,unsigned int n){ int i,j; int temp; for(i=1;i<n;i++...原创 2019-08-15 22:29:30 · 104 阅读 · 0 评论 -
extern 关键字的作用
extern关键字一般放置于变量或函数前,用于标示变量或函数的定义在别的文件中。当编译器遇到此变量和函数时在其他模块中寻找其定义。1. 当出现extern "C"的时候: 主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参...原创 2019-08-08 12:33:44 · 3159 阅读 · 0 评论