C++
文章平均质量分 93
*闲鱼
一名摆烂的全能fw
展开
-
【设计模式】
听别人讲过这样的一个例子,建造玩偶,玩偶存在头部,身体,双手双脚,6个部分,而建造者模式便可以控制这些细节,得到的玩偶是大头儿子还是小头爸爸。该模式的核心思想是限制类的实例化过程,使类在整个应用程序中只能存在一个实例,且通常包含一个静态成员变量来保存这个实例,并且提供一个静态方法来获取这个实例,避免了创建对象的开销,保持数据的一致性。代理模式是一种结构型设计模式,用于控制对其他对象的访问,代理充当了客户和实际对象之间的中介,通过代理对象,客户可以简介的访问实际对象,并在访问过程中添加额外的操作。原创 2023-07-21 00:45:00 · 162 阅读 · 0 评论 -
生产者消费者模型
设置了容器,将卡的钱数放入容器中,在容器中寻找和钱数相同的用户,如果存在说明卡被占用,如果不存在可以进行转账,但是两张卡钱数一样就会发生死锁,所以呢我们可以使用卡的地址,卡的钱数可以相同,但是创建卡的地址肯定不同,所以就解决了死锁问题。生产者消费者相信大家都学过,而这个模型也和名字一样,生产者生产数据,消费者消费数据,这里存在一个队列,生产者生产的数据存放在队列中,消费者消费数据从队列中消费,而容器的大小是固定的,当容器中数据个数大小到达上限时,生产者不能生产,如果容器中没数据,消费者不能消费。原创 2023-06-19 21:35:32 · 313 阅读 · 0 评论 -
C++线程库(2)
在C++线程库(1)的博客中说了互斥量只能解决多个线程访问共享资源的问题,但是很明显没有次序感,而线程安全就是不同线程访问资源但是得到的结果是固定的就这就线程安全,所以为了保证线程安全,互斥锁一般与条件变量搭配使用。我们试着编写一个程序,创建三个线程,调用funa,funb,func函数,依次输出1,2,3,4,5,6也就是线程a输出1,4,7等,线程b输出2,5,8,线程C输出3,6,9等输出到100。),我们举例tha线程获取到锁,他获取到锁之后呢ready为false,进入循环,进入cv等待函数。原创 2023-06-18 01:00:00 · 575 阅读 · 0 评论 -
lambda表达式
该代码中在函数func中使用lambda表达式对全局变量进行了操作,而捕获方式是不捕获任何变量,捕获是针对局部区域内的,所以不存在对全局变量进行捕获,可以在lambda表达式中对全局变量进行操作,但是如果将g_max变成a变量,就会报错,因为使用的是[],不捕获任何变量,但是可以使用形参和表达式函数体中的变量。我们创建一个list容器,并且初始化,删除其中的偶数,就可以用remove_if函数,该函数的参数中使用lambda表达式返回是否为偶数,是偶数就进行删除,不为是偶数就不删除。params是参数表;原创 2023-06-13 01:00:00 · 361 阅读 · 0 评论 -
C++线程库(1)
比如说你去买衣服,有一个试衣间,有两个人要试衣服,一次试一件衣服,而每个人要试好多件衣服,这就出现了竞争,这一个试衣间只能一个人使用,你使用的时候他不能使用,他使用的时候你不能使用,当然为了避免出现两人一起使用的情况,我们会发现门上都有一个锁,这就可以理解为互斥锁,当你试衣服的时候,或获取锁,也就是将门锁起来,锁起来之后其他人无法获取锁而打开门,你用完之后出来就把锁打开,其他人就可以获取锁了。所以呢出现了递归锁。阻塞:读数据,如果没有数据传输过来,就会阻塞住,等待数据传输过来,进行读取,侧重于等待的过程。原创 2023-06-16 01:00:00 · 237 阅读 · 0 评论 -
智能指针(2)
这里我只画了pc对象的结构,其结构都是一样的,创建pa对象的时候,其有三个成员对象,一个是删除器,另外两个是指针,指向堆区的空间,其中一个指针指向我们的Int对象,另一个指向我们在堆区创建的计数器对象,计数器中存在一个指针和两个计数器,其指针指向我们的Int对象,两个计数器分别是_Uses和_Weaks,这里个计数器分别是共享型智能指针和弱引用智能指针。也没有太多要说的,主要是其结构,上面说了计数器类型,其有三个成员对象,分别是ptr指针,指向资源对象,而另外两个便是整型计数器,但是其写法是这样的。原创 2023-06-11 01:00:00 · 365 阅读 · 0 评论 -
智能指针(1)
return 0;我们创建了唯一性指针对象pa,指向船舰的PtrInt对象,可以通过指针来调用类的成员方法。并且会自动析构。错误使用//C }A:使用智能指针管理全局变量是没有意义的,因为程序结束后,指针才销毁,都不如直接定义一个全局变量,其会在程序结束时自动销毁。(智能指针主要依赖局部对象来释放)B:对象本身就是在栈中,而智能指针是处理堆区堆存,所以是错误的。C:该方法本质上不是错误的,因为你用了裸指针,如果发现用了指针还没释放,就会释放两次,导致程序崩溃。原创 2023-06-08 15:54:52 · 681 阅读 · 0 评论 -
STL(结)
这里桶中结点个数是10个,所以存放结点是这样存放的,关键码对10取余,得到的结果是多少就存放在那个结点后面,存放的方式便是链表。而如果数据量太大的情况下,而桶中结点个数很少,这样导致一个结点后的元素个数很多,遍历时元素效率就很低,所以桶的也会进行扩容(更改10),然后重构哈希表(桶)。而每当结点个数等于桶中元素个数时就会扩容。set容器智能存放一种类型,其底层也是红黑树,遍历是有序的,其插入的参数有两个,一个是要插入的关键码类型,另一个是bool类型,可以通过bool类型的返回值判断是否插入成功。原创 2023-06-06 16:28:50 · 299 阅读 · 0 评论 -
C++11右值
/error 不具名对象为右值, const Int & c = Int(3);return 0;无论声明左值引用还是右值引用都必须立即进行初始化,因为引用类型本身并不拥有所绑定对象的内存,只是该对象的一个别名,通过右值引用的声明,该右值又重获新生,其生命周期与右值引用类型名的生命周期一样,只要改右值引用名话或者,改右值临时两就一直存活下去。原创 2023-06-04 14:21:30 · 587 阅读 · 0 评论 -
【STL(2)】
注意双端队列只能通过vector来实现,因为只有vector是连续的空间结构,而优先级队列其实虽然叫队列但是其不满足先入先出的条件,像是数据类型中的堆,每次出队是队列中优先级最高的元素出队,而优先级可以通过元素大小进行定义。我们不看上面Add类的时候就会觉得我们直接调用了函数,实际上是重载了函括号的重载,这就是函数对象,也叫仿函数,有时也叫函子,我们这里的举例因为两个参数,所以是二元仿函数。vector中没有直接的排序,需要调用系统的排序函数,而且只能是从小到大的排序,但是要是想要从大到小的呢?原创 2023-06-02 04:00:00 · 298 阅读 · 0 评论 -
STL库(1)
vector是可以改变大小的数组的容器。其内存结构和数组一样,使用连续的存储空间,也就可以使用指针指向其元素,通过偏移量来访问存储空间中的元素。和数组不同之处在于vector的大小可以动态的变化,容器可以自动扩容存储空间。vector使用一个动态分配的连续存储空间来存储元素,在插入新元素的时候也可能需要重新分配存储空间,也就意味着每次扩容都需要将其元素重新移动到新的存储空间中,很显然这效率是非常低的,为此不会每次像容器中添加元素都重新分配。原创 2023-06-01 01:00:00 · 580 阅读 · 0 评论 -
【异常捕获】
在throw中捕获到异常之后会通过异常类来创建一个异常对象来通过catch来解决这个异常,如果没有解决这个异常会跳出这一层,谁来调用这一部分,在上层来找catch来解决这个问题,如果在主函数中都没找到,那么会通过操作系统来终止程序处理。在C++语言本身抛出异常(new失败,STL),第三方库,系统库的接口抛出异常时,可以使用异常捕获机制。异常时程序可能检测到的,运行时不正常的情况,如存储空间耗尽,数组越界等,可以预见可能发生在什么地方但不知道在什么时候发生的错误。例如上面两数相除的程序,分母为0便是错误。原创 2023-05-30 01:00:00 · 588 阅读 · 0 评论 -
类型转换(2)
其输出结果是的d,c,b,a,0x61626364,我们的计算机是小端存储,所以地址存放低位,高地址存放高位,cp为低地址,存放16进制的64,而16进制的64转换成10进制就是100,正好是字母d的ASK码值,然后依次移动1字节,也就是63,62,61对应cba,对应输出结果是dcba。思考上面代码输出结果是什么?运行上面一段代码就可以应正我们的结论,在指针和引用转换的前提下进行上行转换,动态转换和静态转换都是一样的,但是在值转换的时候,动态转换就会报错,但可以将派生类对象转换为基类右值引用。原创 2023-05-27 01:00:00 · 729 阅读 · 0 评论 -
类型转换(1)
将Circle的指针强转成Square类型的指针,输出结果是什么,首先两个类的大小是相同的但是Circle中radius是float类型,Square中length是int类型,所以呢其解析方式不一样,将int类型的12解析成float类型,输出结果为1094713344。rd移动move转换呢,他可以识别常性,其内部是叠加的,常性左值叠加右值仍然是一个常性右值引用,但是没有处理常性右值引用的函数,所以调用的是常性左值引用。我们大致可以这么理解,可以取地址的值为左值,不可以取地址的值为右值。原创 2023-05-23 01:00:00 · 380 阅读 · 0 评论 -
纯虚函数与抽象类
在上一次博客中写到了这么一段代码:我们发现这段代码的问题出在析构的时候只会析构obj对象,不会析构Base对象,这是什么原因呢?因为在编译过程中op是obj类型的指针,所以就将op和obj类型进行了绑定,析构的时候同样也就只析构了obj类型,造成了内存泄漏。但是怎么解决这个问题呢,我们可以给obj类的析构函数加上virtual关键字,将其变成一个虚函数,这样析构的时候就是动态联编,析构时查看虚表看其指向的是哪个对象的析构函数,然后进行析构。当你的类的成员函数中存在虚函数,就需要将其析构函数设置成虚函数。原创 2023-05-20 01:00:00 · 330 阅读 · 0 评论 -
多态与虚函数(补)
很显然我们创建Base对象的时候首先会创建obj对象,所以首先会调用obj的构造函数,此时虚表指针指向obj的虚表,所以add(12)调用的是obj的add函数,然后创建完成之后创建Base对象,此时虚表指针指向Base虚表,所以此处的add查找的是Base的add,然后析构开始进入Base的析构函数(重置虚表指针),在~Base的时候调用add调用的是本类型的add函数,然后析构基类,在析构派生类的时候虚表指针已经被重置,指向了obj的虚表,所以析构基类时查找的也是obj的虚表。原创 2023-05-16 00:45:00 · 285 阅读 · 0 评论 -
多态与虚函数
如图便是三个类的虚表,实在编译时就确定了的,例如obj派生出了Base类,所以Base的虚表就是将obj的虚表拷贝了一份然后进行同名覆盖,而在创建对象的时候,我们以创建Test对象为例,创建该对象首先创建Base,而创建Base需要创建obiect,而当类中有虚函数时类的大小就会多4(32位)字节,用于存放指向虚表的指针,创建Test时,指针首先指向object的虚表,然后指向Base的虚表,最后指向Test的虚表,根据其构建顺序。函数的重载,运算符的重载,属于编译时的多态性。原创 2023-05-13 00:00:00 · 468 阅读 · 0 评论 -
C++面向对象编程
类的数据成员多为私有的,不能从外部进行操作,因此需要通过公有的成员函数进行操作赋值,而构造函数便是再创建对象的同时进行初始化的函数,注意只能初始化一次。创建对象初始化对象类型转换函数名同类型名无函数返回类型,此处并非void,即什么也不写。其实构造函数本质上存在返回类型,同类名,返回的就是我们创建的对象。程序运行时,当对象被创建时自动调用构造函数,并且只能调用一次,生存期也就仅仅这一次调用。原创 2023-05-09 09:56:05 · 1010 阅读 · 0 评论