- 博客(35)
- 收藏
- 关注
原创 智能指针的使用及原理
对于为什么要有智能指针,以及在什么场景下使用智能指针、如何使用的问题,我们可以通过下面这段程序来进行分析,代码如下:这段代码的功能就是一个除法运算,但是在调用func函数时,动态开辟了两段空间arr1和arr2,当除数不为0时,就正常执行代码,并正常释放arr1和arr2;当除数为0时,就抛出异常通过栈展开的方式,捕获异常,代码中先用catch(…)的方式对异常进行捕获,就是为了先释放arr1和arr2,然后再对异常进行抛出,最后在main函数中被捕获。从结果来看,代码好像并没有什么问题,抛出的异常都能被
2025-05-28 11:46:00
1270
19
原创 C++11-(3)
虽说push_back是构造+移动构造,但是移动构造的效率也是足够低的,对于深拷贝的类型,就与emplace没有多大的差别,但是对于浅拷贝的类型,还是有一定的差别的,浅拷贝,若开的空间太大,也要一个字节一个字节的拷过去,所以总体上来说,还是emplace的效率更高一些。emplace与insert是等价的,emplace与emplace_back也是等价的,功能上都是插入数据,但是还是可以看到,insert和push_back接口插入的是一个左值或者右值,而emplace系列的接口插入的是一个参数包。
2025-05-23 12:04:50
1473
19
原创 C++11-(2)
lambda表达式本质是一个匿名函数对象,跟普通函数不同的是它可以定义在函数内部。lambda表达式对于语法使用层面而言没有类型,所以一般是用auto或者函数模板参数定义的对象去接收lambda对象capture-list:捕捉列表,该列表总是出现在lambda函数的开始,编译器根据捕捉列表来判断接下来的代码是否为lambda函数。捕捉列表能够捕捉上下文中的变量lambda函数使用,捕捉列表可以通过传值和传引用捕捉,捕捉列表为空也不能省略parmeters:参数列表。不传参时可以连同()一同省略。
2025-05-18 10:59:36
1028
20
原创 C++11
列表初始化已经很方便了,但是对容器初始化就不太方便了,比如一个vector对象,若要用N个值去构造初始化,而N是不确定的,那么需要实现很多个构造函数才支持,所以C++11库中提出了一个std::initializer_list的类,该类也是一个容器但特殊的是它在底层开一个数组,内部有两个指针分别指向数组的开始和结束,所以可以支持任意多个同类型的对象,从头开始遍历数组,将数据拷贝依次拷贝到需要初始化的容器中。右值引用与左值引用没有太大的区别,都是取别名,左值引用就是给左值取别名,右值引用就是给右值取别名。
2025-05-11 15:29:57
1402
20
原创 哈希封装unordered_map和unordered_set的模拟实现
unordered_map的底层复用了哈希表来实现key/value的结构,而unordered_set的底层也是复用了哈希表,但实现的是key的结构。,这就是它们底层复用的封装不同所导致的,map和set的底层是红黑树,迭代器在遍历时走中序遍历,所以打印出来的数据是有序的,而unordered_map和unordered_set底层是哈希表,哈希表是通过哈希桶来将值一个个存储进去的,迭代器遍历时是遍历一个个哈希桶,所以底层复用的不同,实现出来的效果也略有不同,但是这几个容器的使用方式完全是类似的。
2025-04-27 15:56:23
539
12
原创 认识哈希以及哈希表的模拟实现
概念:哈希(hash)又称散列,是一种组织数据的方式。从译名来看,有散乱排列的意思。本质就是通过哈希函数把关键字key跟存储位置建立一个映射关系,查找时通过这个哈希函数计算出key存储的位置,进行快速地查找举个例子:哈希最简单的一种方式就是直接定址法,当关键字的范围比较集中时,直接定址法就是非常简单高效的方法,如一组关键字值都在[a,z]的小写字母,那么我们就可以开一个有26个空间的数组,每个关键字通过一个哈希函数计算出要存储在数组空间的位置,该哈希函数。
2025-04-26 16:47:03
1899
18
原创 封装红黑树模拟实现map和set
map是key/value的搜索场景,set是key的搜索场景,这两个容器的底层,竟然是一致的,这是为什么呢,其实底层的红黑树用了一个巧妙的泛型思想来实现的,红黑树在实现key和key/value的搜索场景时不是写死的,而是由红黑树的第二个模板参数决定结点中存储的数据类型,若红黑树的第二个模板参数传的是key,那就是set的搜索场景,若是键值对,也就是pair<k,v>,那么就是key/value的搜索场景,这样既可以实现key搜索,场景的set,也可以实现key/value场景的map。
2025-03-28 20:35:01
1237
12
原创 C++红黑树实现
红黑树的概念:红黑树是一棵二叉搜索树,他的每个结点增加一个存储位来表示结点的颜色,但颜色只能是红色或者黑色。它是通过约束任何一条从根到叶子结点上的颜色来控制平衡的,这样就会确保没有一条路径会比其他路径长出两倍,因而红黑树接近平衡结点颜色只能是红色或者黑色根结点必须是黑色若一个结点是红色,那么它左右孩子的结点只能是黑色,换句话说就是,不能有连续的红色结点(注:若红色结点的孩子结点为空,那么该“空叶子结点”也是黑色的对于任意一个结点,从该结点到其他所有空结点的简单路径上,均包含相同数量的黑色结点。
2025-03-23 11:17:42
1259
14
原创 C++异常
上面的代码分析,当调用func函数,输入值,然后调用Divide函数,若b为0时,就会抛出一个异常,上述代码中抛出是一个string对象,那由哪个catch来捕获呢,是Divide函数中的catch来捕获吗,不是的,根据C++的捕获规则,是由与抛出对象类型匹配以及是离抛出异常位置最近的catch来捕获,那么上面的代码中,符合规则的只有main函数中的catch。重新抛出异常,有时候不是为了对异常进行处理,可能是先捕获下来,对一些开辟的空间进行释放,或者特殊的情况先进行处理,处理完之后再重新抛出异常。
2025-03-17 10:17:30
824
10
原创 map和set的使用
set是一个关联式容器,关联式容器逻辑结构通常是非线性结构,两个位置之间右紧密的联系,交换一下,它的存储结构就被破坏。set的底层是红黑树,红黑是是一棵平衡的二叉搜索树,set是key搜索场景的结构set声明的结构如下图:第一个模板参数为关键字的类型,也就是key的类型第二个模板参数是仿函数,用来控制关键字的比较方式,这里默认支持小于的比较方式,若不满足自己的需求,可自己实现一个仿函数。
2025-03-04 14:23:42
1393
8
原创 继承
概念:继承是面向对象的三大特性之一。继承在现实生活中的说法就是继承了家里的家产,继承了家里的家业,从长辈那直接得到,而在C++中则是解决一些复用的问题,内层次的复用,它允许我们在保持原有类特性的基础上进行拓展,增加一些成员变量或成员函数,产生新的类,该种类就叫派生类。一句概括就是继承是类设计层次的复用。
2024-12-10 16:53:08
1169
11
原创 #C 函数递归
这个例子其实是一个错误的示范,会导致这个函数无限递归下去,无限递归会出现栈溢出的错误,因为每一次调用函数,都要为这一次函数的调用分配内存空间,二内存的空间是在栈区上分配的,所以会出现栈溢出(stack overflow)的错误。上面的图片清楚的展示函数是如何将递归的,就是将实数不断的递推出去,然后将返回值不断的归回来,最后得出最终的返回值。函数递归一定要满足上述两个条件,没有条件就会出现栈溢出,空间不足的错误,就如我上面举到的例子。它的递归条件就是当n=0时,停止对函数的调用,返回值为1.
2024-04-27 20:37:52
376
原创 c# 循环结构 break和continue的用法
从这个代码可以说明,当i为4时if条件为真,执行break语句,而printf语句和i++语句将不会执行,且while循环体终止,输出的结果就为1 2 3,这个语句相对来说也是很好理解的,其实break翻译过来也就是"打断"的意思嘛,打断两人之间的对话,打断循环体,是一个非常常用的语句。首先,1赋值给了i所以满足i<=5的表达式所以为真,i为1被打印了出来,之后i++使i=2又满足表达式2<5,i为2被打印了出来,以此类推,直到i>5,表达式为假,结束了循环。break的作用就是终止循环,直接跳出循环体。
2024-04-14 12:06:38
945
原创 C# 分支结构
通俗的来讲,表达式就相当于一把可以变换数字的钥匙,case1和case2还有default就相当于门,如果钥匙变化成了数字1这把钥匙就可以开case1的门,如果不是数字1也不是数字2这把钥匙就可以开default的门,这些门就相当于多个结果。当然case的个数是由问题本身决定的,可以有很多个,defualt可以有也可以没有,也是根据问题来决定的。需要注意的是,switch后面的表达式必须是整型的,case后面必须是整型常量。当i%3为1时,程序就会自动跳到case为1的语句中,输出余数是1。
2024-04-14 12:05:38
338
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人