- 博客(184)
- 收藏
- 关注
原创 理解数据库中树的高度越高涉及到的磁盘IO越多
在数据库中, 经常会涉及到一个问题, 就是B树和B+树,涉及到这两个数据结构, 往往涉及到一个问题, 就是B树和B+树的树的高度要比平衡二叉树的高度低, 这会降低很多的磁盘IO操作.都说可以降低磁盘IO, 那么怎么理解呢?-- 以下是自己的理解, 如有错误,欢迎指正.
2024-10-03 18:43:59
397
原创 c++中std::find()函数
就可以使用全局的find实现在一定范围内查找某样数据, 当然你也可以直接使用循环在指定范围内比较比较. (原因: 对于容器内置的find()函数是专门对于当前容器的结构进行设置的, 其内部可能会有相应的优化,find函数在容器的内部已经存在了,但是stl还提供一个全局的find函数.), 使用这个函数可以避免重复造轮子.两个圈定范围的迭代器。传递两个指针指定范围。
2024-09-22 17:43:58
585
原创 Vmware打开的时候提示正在使用,重新获取所有权
在正常关闭虚拟机后,vmware会自动删除这个锁。所以下次再启动虚拟机时,vmware还会误认为需要启动的虚拟系统已经正在运行,就出现了提示this。这个lck文件是虚拟机的磁盘锁文件,我们知道虚拟机的磁盘与主机的磁盘是共存的,只是由于采用特定的虚拟机制,使二者互不影响。在使用虚拟机时,vmware就会生成若干磁盘锁文件,用以保护当前虚拟机占用的磁盘不会被主机或者其它虚拟机占用修改。这是因为之前关闭虚拟机的时候没有正确的关闭导致的情况,我们可以下对应的虚拟机文件下重新加载相应的系统,
2024-08-14 10:24:40
341
1
原创 异步IO函数返回情况
在执行异步IO的时候,调用函数之后程序不会阻塞,可以执行别的任务,异步函数不会立即返回,当系统操作结束之后会通过之前的约定来提示程序(比如回调函数,事件等)返回,返回的时机,不同系统的性能 不同返回的时间也不同。
2024-08-06 08:37:08
100
原创 c++使用memset()在类内将对象的属性都设置为0,memcpy()可以实现赋值属性
一般情况,防止垃圾值,我们在定义类对象或者结构体对象的时候不指定其属性的值的时候,就是调用其默认构造函数,因为此时没有给属性赋值的话可能会出现垃圾值的问题,所以我们在默认构造函数内部将当前对象的所有属性都设置为0, -- 所以在默认构造函数中我们一般会给属性0值。
2024-07-29 17:02:10
196
原创 c++的结构体绑定 -- c++17
auto[变量名],就是结构体绑定的语法,其就是根据返回值的结构推算出你指定的对应变量名的类型,然后赋予其对应的值,我们这里直接使用一行代码就可以,切换到c++17标准,如果编译器支持vs中可以右击项目->属性->C/C++->语言->C++语言标准->设置为c++17就可以。但是有了c+17的结构体绑定,使用tuple是在获取其对应的值是也可以做到顾名思义,而且代码更加的清爽。在c++17提出结构体绑定的时候,我们返回多个数据的时候优先是使用结构体的,具体原因可以查看。而且相比结构体所写的代码要少。
2024-07-28 00:11:11
435
原创 老版本的vs,在使用多线程的时候需要手动设置
老版本的vs需要手动设置支持多线程的DLL,属性->C/C++->代码生成->运行库->选择多线程。当然较新的编译器都是默认支持的,不需要手动设置。
2024-07-26 22:26:14
283
原创 RTTI的开启和关闭
我们使用dynamic_cast就是基于RTTI的,我们可以通过编译器对RTTI进行开启或者关闭,关闭之后dynamic_cast就无法使用。RTTI是运行时类型识别,C++引入这个机制是为了让程序在运行时能根据基类的指针或引用来获得该指针或引用所指的对象的实际类型。我们可以右击项目,然后选择属性->C/C++->语言->启用运行时类型信息,这样就可以开启或者关闭相应的RTTI了。而linux中可以以其它方式开启或者关闭,比如可以借助编译器的选项进行开启或者关闭,选项来关闭 RTTI。
2024-07-26 22:23:00
545
原创 c++typeid()的使用
public:public:public:// 使用多态return 0;对应的输出结果已经在函数调用之后了,记住typeid函数返回一个type_info类型的对象,但是我们不能使用这样的类型去接收,因为外部不可定义其对象,所以获取type_info类型只有通过typeid,所以获取之后直接使用这个对象。代码中调用name()获取具体对象的类型。
2024-07-25 13:05:06
949
原创 利用errno判断当前程序执行的状态
在linux函数中,函数执行失败返回-1,但是我们只知道出现了错误,但是并无法得知是出现了什么错误,这时候我们可以借助errno来判断,导入头文件#include 。比如,程序中某个函数在某种状态之下发生错误,我们需要进行特殊处理的时候,我们就可以使用errno判断是否和对应触发的宏相同,如果是那么我们就可以在此状态下进行特殊处理的操作。当对应的函数返回-1的时候,操作系统会将对应的错误信息写入到errno中,并且不同函数对应的值不同,但是无需记忆,使用的时候进行查阅就可以了。
2024-07-21 12:35:15
129
原创 read读到缓冲区为空返回什么
在阻塞模式下,如果缓冲区为空,read函数会阻塞当前线程,直到又数据可读才会返回读取到的字节数。如果已经到达文件结尾,无论文件描述符是阻塞还是非阻塞,read的返回值是。如果缓冲区为空且文件描述符被设置为非阻塞模式,read函数会立即返回-,并设置errno为EAGAIN(表示"再试一次" 或 "资源暂时不可用")。如果缓冲区为空切文件描述符是阻塞模式,read函数会阻塞等待有数据再进行读取。默认情况下,它们的缓冲区read操作是阻塞的。
2024-07-21 12:29:27
310
原创 系统调用简单介绍
简单理解就是操作系统给我们提供的函数接口,这些接口就是系统调用。那什么样的操作是只有操作系统才能完成呢?比如: 当我们需要申请内存,或者申请使用硬件资源的时候,这些操作我们都需要通过操作系统来完成,也就需要使用系统调用了。比如我们熟悉的输出函数printf(),,但是它是通过对系统调用进行封装才实现的,因为我们将数据输出到控制台,是需要使用到硬件资源的,所以必须调用系统调用,printf()是为了我们使用更加方便在系统调用的基础上进行了封装。,来将对应文件中的数据读取或者写入。
2024-07-03 21:49:42
476
原创 错误:程序报错,我们命名已经定义了对应的类型,并且对应的函数也写的没问题,但是编译之后还是会出现类型不对或者函数参数不对的问题
上图中,是出错的一个例子,GroupType类型我们在程序中已经定义过了,TalkWindow()函数也已经实现了3个参数的函数重载。但是还是会报错。
2024-06-24 23:33:30
368
原创 linux中使用socket通信的时候无法连接的问题原因
可能是你禁止了对应的linux工具使用相应的网络,所以其无法传送,一般是专有网络等,可以在设置里面允许其访问这些网络这样就可以传输成功了。
2024-06-18 09:33:59
367
原创 c++11 lambda匿名函数
就是一个没有名字的函数,和匿名对象类似,其只会在所在行起作用。举个例子: 我们之前使用过sort()排序函数,其可以根据你传入的一组数据,根据某种规则进行排序,规则我们既可以自己指定,也可以使用默认(sort()默认是从小到大排序,如果是C语言的话这个必须得自己指定)。如果,我们希望自己指定排序规则,,使用函数指针,sort()函数会对其进行回调。,就是一个类中重写了函数调用运算符()的函数,然后sort内部也可以进行调用。
2024-06-09 16:43:10
774
原创 c++ namespace以及使用建议
下面,我们自定义两个命名空间,然后对齐都进行using,内部包含一个同名函数,当我们去调用getAge()的时候会报错,因为,你同时using的两个命名空间中都有这个函数,编译器不知道用哪个,这就是。当然,将using namespace放到头文件中那更是不行的,因为头文件会到处包含,包含其的文件中可能也存在using namespace,这时候很容易出现下面的问题。在写c++代码的时候,经常会使用标准库中的函数,使用之前我们必须在前面添加一个std::,因为c++标准库的函数是在命名空间std下定义的。
2024-06-08 11:49:20
432
原创 reserve函数使用注意事项
但是,在你没有向内部取放数据的时候其还不属于你,所以,在你v1.reserve()之后直接去访问内存会出问题。[] 不具备开辟空间的能力,其只是访问对应的空间,但是这篇空间虽然已经预留,但是它还不属于你,所以你无法访问。我们之前提到过,在vector动态开辟空间的时候,如果空间不够其会重新开辟,然后进行数据拷贝,这会带来一定的性能问题。就是reserve函数会根据你传入的数据,在一块内存中找到对应长度的连续空间,先预留起来,也就是不会被别的数据占用。注意这块内存目前还不是你的,只是预留下来给你用的。
2024-06-04 12:58:33
319
原创 offsetof宏 -- 获取结构体或者类中数据偏移
所以,此处Type中int类型为最大的类型,占用4字节,所以其偏移值必须是4的整数倍,所以这时候就会发生内存对齐,char本来占用1个字节,发生内存对齐之后,为4字节,偏移就是0-3,因为结构体数据是连续存储,所以接下来的a的偏移就是4,这样其的偏移值就是4的整数倍了,又因为此类型最后一个类型为char,值占用一个字节,这样占用的总字节数为4+4+1 = 9 ,并不是4的倍数,所以又会发生内存对齐,对齐到12,这时候就是4的倍数了,所以这个结构体占用的空间是12个字节。那么为什么偏移值为8呢?
2024-05-30 14:03:11
369
原创 c/c++内存操作函数
这些函数在字符串操作函数的那一节提到的函数好像都是类似的。区别在于,那块的函数主要用于操作字符串,这里的函数用于操作内存。简单来说就是可以操作任何类型,因为其参数接受的是void*类型的(任何类型的指针都可以隐式转换为void*类型的指针)如果你是要操作字符串,那么可以使用相应的字符串操作函数,如果是要操作别的类型,那么可以使用这里提到的函数。
2024-05-28 10:10:52
954
原创 C语言常用字符串处理函数
C语言中包含了很多对字符串处理的函数,要使用这些函数,首先需要导入头文件例: char *str = "abcde";// 结果为5strlen()计算的结果是字符串所占有的字节数。
2024-05-27 12:23:41
831
原创 结构体常见问题
int x;int y;}pos;定义一个结构体,其内部又定义了一个同类的结构体变量,这是一种错误。(因为如果你在结构体内部定义自己类型的结构体变量,在定义结构体的过程中,它会不断地去创建新的结构体变量,一直递归下去,没完没了) -- 有的编译器会检测到这种错误的写法。我们可以在结构体内部放一个指向自己类型的指针,这样就不会出现上面的问题了。int x;int y;}pos;
2024-05-27 09:06:01
422
原创 为了可读: 使用typede给函数指针类型取别名(c++中也可以使用auto自动推导)
在这行代码中,我们使用了函数指针,但是你会发现函数指针的类型很晦涩,所以为了更加的可读,我们不建议直接使用这种类型。,这样咋后面定义函数指针的过程中,使用别名定义即可,就不需要写像代码中这种类型了。对于上面的代码函数指针类型为: void (*)();,同样也不用写这种晦涩的类型)
2024-05-26 15:32:22
180
原创 求两个整数最大公约数的方法
可以使用递归来实现,编写gcd函数返回最终的结果(最大公约数)。传入两个参数,如果存在一个数字不大于0就返回0,利用上面的公式就可以得出最后的结果。
2024-05-26 09:57:08
119
原创 c++11 auto类型推导的使用建议和注意事项
首先c++是强类型语言,也就是在定义变量的时候必须指定具体的类型。像我们常用的int,float,char等等都是类型,auto关键字原本的意思是说明某个变量是自动变量,c++11提升了它的功能。在c++11之后,我们可以使用auto来进行类型推导。// int// long// float// double// char// Student 自定以类型。
2024-05-25 15:28:58
710
原创 无符号整形(size_t)使用时候的注意事项
(但是请注意: 对于负数而言,有符号数和无符号数的值可能不仅仅是正负的区别,数值上也是不一样的,比如: 1000 0001 : 有符号数为: -1 , 无符号数为: 129)// 这行打印语句的输出结果为1,也就说明后面的比较表达式返回的结果是1,也就说明s1-s2的值是大于0的,但是对于有符号数而言它的结果是-1,应该比0小才对。所以:上面所说的问题出现的原因是: 你在声明变量的时候使用的是无符号数,因为这个变量不会为负,但是如果两个无符号数相减,那么小的减去大的。那你看下面的打印语句。
2024-05-24 12:15:40
345
原创 C语言中的可变参数
函数的参数是函数的一个重要的组成部分,但是,我们平时指定的参数都是固定的。比如:func(int a,int b);如果当函数的参数个数很多的时候,我们可能要写很多的向上面一样的参数,显然效率不高。那么有没有一种方式可以改善。C语言中提供可变参数,比如printf()就使用的是可变参数,我们只需要在前面传入一个字符串,后面就可以指定任意的个数的数据,这是因为它使用的就是可变参数。那么下面来谈论可变参数如何自己使用。
2024-05-23 15:44:30
354
原创 堆空间和栈空间的区别(主要说分配和简单介绍)
所以堆空间和栈空间的区别主要在分配,这也能直观的看出为什么栈空间的效率高,所以我们应该优先选择栈空间,当然如果需要用到堆空间的时候,依然要使用堆空间。(例如: 需要大空间,变量的生命周期由自己控制,函数返回数据等等)。
2024-05-22 22:15:27
2064
原创 位数组,以及自己实现的相关的操作
位数组就是存储的都是0,1的数据,因为程序中无法直接使用二进制,所以我们使用最接近的char类型的数组来表示位数组。可以更加方便的进行操作。
2024-05-22 12:29:15
113
原创 c++翻转一个无符号数的二进制位
看下面代码: 注意我们使用的数据类型并不是一个字节,所以说不一定是八位,而且不同的系统一个字节对应的位数有所不同。就是将一个数对应的二进制位进行相应的翻转,比如: 0000 0101 翻转之后: 1010 0000。
2024-05-22 11:01:43
304
原创 c/c++使用void*实现类型通配
这个函数是我们自己编写,然后传入到调用的函数中去的,所以其内部需要提供一些功能,就是帮助调用函数中需要访问或者操作void*数据的部分,我们可以调用这个函数来实现,因为这个函数使我们自己提供的,我们知道自己此时要处理的具体类型,所以可以根据需求在函数指针指向的函数内部将void*转化为具体的类型,然后进行操作。我们封装一个函数,比如是一个比较函数,用于比较两个数据的值, 如果我们将参数的类型写死,那么这个函数就只能去处理此种类型的数据,对于其它的类型我们还需要进行函数的重载。进而实现一个函数处理多个类型。
2024-05-20 12:15:55
235
原创 c++11 tuple元组
tuple也是一个类模板,所以,当我们需要存放多个不同类型的数据的时候,可以使用tuple。函数如果要返回多个不同类型的时候,也可以使用tuple。
2024-05-20 11:04:53
751
原创 使用模板传入具体的类型的数据
但是,我们前面说到,模板如果我们不去使用它,它就是一个模板,不真实存在。所以,上面我们在类模板的成员定义一个数组,数组的大小由一个模板参数SIZE指定。在没有使用的时候,它不真实存在,所以这样写没有问题。我们知道,在c或c++中定义数组的时候,数组的大小必须在编译的时候就得确定,所以我们在正常情况是不能使用变量来指定数组长度的。它是一个具体类型的数据,我们这里传递它的目的是作为数组的下标。在c++标准库中的array其实和此场景是类似的,我们在使用的过程中需要传递一个整数来指定内部数组的大小。
2024-05-19 16:35:40
139
原创 priority_queue:底层用堆实现
STL中的优先队列,底层是使用堆的结构实现的,如果我们在一定场景中需要使用到堆的结构,就可以使用priority_queue来表示。(默认情况是最大堆)
2024-05-19 10:36:04
115
原创 c++: ->运算符的用法 -- 获取结构体和类中元素偏移
首先,Student的首元素为int类型的,所以其第二个元素的偏移值就是sizeof(int) = 4字节;我们要找到第二个元素,就直接用Student的首地址(指针stu记录的地址)加上4,就可以得到第二个元素的地址了。(这里使用的是Student的指针,如果是直接创建对象也是类型的,变量的地址就是首地址)上面的代码,我们将地址0转换为对应的类,然后去访问内部数据。对于开辟的Student的空间,其存储结构大致是这样的,->运算符对于指针来说是很常用的,也很方便。问题: 0的地址不是禁止操作的吗?
2024-05-17 10:02:04
350
原创 c++ std::vector 的优化使用
我们往vector中存放数据的时候,如果vector的空间不够了,那么它就会在内存的另外一个位置,重新开辟一块足够存放数据的内存,然后将以前内存中的数据拷贝到新内存,然后将新增数据也放到内存中,最后将以前的旧内存释放带掉。首先这段代码,会先创建一个Student()的对象在函数的堆栈内存上,然后将该内存的数据存放到vector管理的内存上,这就要将堆栈位置的数据拷贝到vector对应的内存。其不会在函数的堆栈内存中创建对象,而是直接在vector管理的空间上使用传入的参数,调用对应的构造函数,创建对象。
2024-05-15 14:28:18
567
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人