C++
文章平均质量分 55
各类有关C++的知识
见牛羊
化繁为简
展开
-
shared_ptr放入vector,要及时clear,避免内存泄漏
最近碰到一个内存泄漏的问题,查了半天发现是vector数组的成员中有共享指针,而vector没有释放引用计数导致的。可以看到,因为使用了vector而没有清空,增加了智能指针的引用次数,但是在使用完vector之后没有释放,到时计数没有回归。我们看看嵌套一个结构体,结构体里也有一个共享指针会如何。这里我们来引深一下,为什么放入Vector之后,原创 2024-02-14 18:54:55 · 1265 阅读 · 0 评论 -
回调函数的使用详解
把我们自定义的函数注册到一个全局函数指针的变量中,然后在程序需要用到的时候,调用它。原创 2024-06-26 17:20:37 · 587 阅读 · 0 评论 -
将double类型转为两个float类型存储(顺带看看初版到最终版的优化思路)
实际工作中碰到一个需求,将一个double类型的变量,存储成两个float类型。最后再根据两个float类型转回double类型。因为实际的信号列表已经定义了好了两个float类型,所以只能以这种折中的方法将double类型存储下来。原创 2024-03-30 10:57:21 · 299 阅读 · 0 评论 -
C++ 关键字小结
delete 的作用和=default 有点相反,是显式的表示不用某个默认的函数。比如,有时候我们不想使用默认的拷贝构造函数,就可以写如下的代码。比如,用户如果写了自己的构造函数,那么编译器就不会创造默认的构造函数了,这有可能会带来编译错误。在执行A a3 = a1;=default 一般会放在默认的构造函数,析构函数,拷贝构造函数,拷贝赋值函数,原创 2024-02-14 21:31:07 · 189 阅读 · 0 评论 -
C++单例模式详解
起因是在程序中重复声明了一个单例模式的变量,后来程序怎么调都不对,最后发现变量是用单例模式,修改是全局的,所以决定好好梳理一下单例模式。首先,为什么要用单例模式,就是因为我们希望一个类只有唯一一个实例,并且提供一个全局的访问点。从这个描述不难看出,这个实例应该是要static来修饰的。。原创 2024-02-05 16:44:08 · 2531 阅读 · 0 评论 -
C++:constexpr 和 const 的区别
constexpr 是 C++ 11 标准新添加的关键字,原先的标准中是只有const关键字的,作用是表示只读常量。但是,其实只读常量是两个属性,分为只读和常量,都用const来表示会产生歧义。这里补充const的一个重要概念就是,const后面的变量,仅仅表示不能通过该变量改变背后实际的值,但是如果其他变量也能够表示同一块内存空间,这个内存空间里的值是可以通过其他变量来改变的。上面的程序做如下修改,arr2就可以正常的编译,因为传入的是一个constexpr代表的常量类型。原创 2023-09-18 19:10:07 · 308 阅读 · 0 评论 -
C++小技巧, vector的resize,reserve和push_back
在使用C++的vector时,一不注意就会是的vector越界,或者在push_back后遍历vector发现前面的值根本不是自己想要的值。可以明显看到,resize之后,vector的size变成了5,而在push_back之后size变成了6。而往往我们想事先初始化vector的空间,其实应该使用reserve,而不是resize。原创 2023-08-25 17:09:11 · 775 阅读 · 0 评论 -
Eigen::Matrix的6个模板参数含义
Eigen Matrix 模板参数解释原创 2023-03-20 19:26:04 · 437 阅读 · 0 评论 -
C++面经总结1——类相关
C++面经自己整理,按主题发出,本偏主要和类相关原创 2022-11-13 19:28:31 · 498 阅读 · 0 评论 -
C++编译过程详述
想总结一下这个问题是我突然有一天好奇编译头文件和编译头文件对应的源文件有没有区别,因为写makefile的时候依赖即可以写头文件,又可以写源文件。在网上查了半天,估计我的这个问题比较stupid,也没有明确的回答。索性顺藤摸瓜看了看C++的编译过程,虽然之前大致有个了解,但不够仔细。这一看发现,区别肯定是有的(尽量编译源文件而不要尝试编译源文件对应的头文件)。但更重要的是,把编译过程清楚捋一遍,解释了我之前不少的疑惑。而学c++的时候上手就是vc6.0,对理解编译过程太不友好。所以还是应该有个全面的认识。(原创 2021-08-11 12:57:25 · 676 阅读 · 0 评论 -
前置递增运算符(++)比后置递增运算符效率高的原因
前置递增运算符比后置递增运算符效率高,当然递减运算符也是一样的。我一开始是不理解这句话,而且在接触程序之初,似乎更习惯用后置的情况,即经常会写成i++。前置的形式是返回递增或递减之后的对象,只需要返回该对象的引用。而后置的形式返回的是递增或递减之前的对象,因此需要额外创建一个对象副本,返回的不是引用,而是这个副本对象。虽然有点抽象,但是上面这段话可以说就是标题的回答了。下面把上面这段回答翻译成人话,啊,不,翻译的直观一点~。从两个方面来说明,使用效果上和实现方法上。使用效果上。对于++i和i+原创 2021-08-08 17:27:36 · 709 阅读 · 0 评论 -
C++ STL 迭代器用法总结
最近写东西用到了unordered_map容器,然后想要逆向遍历一遍哈希表,结果报错。研究了一下发现STL中不同容器对应的迭代器有很大的区别。关于迭代器,之前一贯粗浅地按指针来理解了,借此机会详细总结一下。1. 迭代器说明迭代器的作用是介于容器和算法之间,迭代器大致分为5类:随机访问迭代器,单向迭代器,双向迭代器,输入迭代器,输出迭代器。其中主要使用的,也是最重要的是前三种。随机访问迭代器:支持通过偏移量访问,比如it+5。单向迭代器:一般都是正向,仅支持++操作,不支持—操作,不支持偏移量原创 2021-08-07 15:12:42 · 606 阅读 · 0 评论 -
Const在函数前后的区别
知识点小结:const放在函数后主要是限制类中的成员函数,const放在函数前是限制函数返回类型为指针时通过指针对返回值的修改。const在函数前:Const在函数前实际上是约束函数的返回的,表明返回的值不能做左值,实际上就是防止返回值直接被赋值。但是一般的变量无法修改函数返回值,其实是为了防止函数返回类型为指针类型时,通过指针对返回值进行修改。非指针的函数返回类型前加const是没有意义的。示例如下。特别注意,要用const int* 类型的变量接住函数的返回值,如果只用int* 类型是不原创 2021-07-21 18:55:48 · 6776 阅读 · 0 评论 -
函数参数中指针传参和引用传参的区别
引用符号&和指针*都可以在函数参数中出现,但使用上是有区别的。首先这两种用法如果在函数中对传入的参数有所改变,那么这种改变是会一直保留的,不会在函数作用域外就恢复。当然,也有很多时候我们不希望传入的参数被人为的改变,这时候可以使用const关键字,关于const和引用符号&的搭配,防止传入参数被改变的情况可以参考这篇文章虽然引用和指针的方式作为传参方式都会保留该函数对传入参数的改变,但这两种方法还是有区别的。这个区别表现在,引用的方式下可以直接使用该参数,而指针的方式通常都需要解引用,或原创 2021-07-20 19:59:40 · 3861 阅读 · 2 评论 -
C++ 深拷贝、浅拷贝和拷贝构造函数
浅拷贝:浅拷贝就是指不重新申请新的内存空间,仅仅是给原来被拷贝的量取了一个别名。这两名字都是共用的同一块内存空间。最典型的就是指针变量赋值。在通过一个指针修改了内存空间中的内容后,另外的指针也会发生相应改变。如下所示:#include <iostream>using namespace std;void test1(){ int* p1 = new int(1); int* p2 = p1; cout << "*p1 = " <<原创 2021-05-15 14:34:21 · 312 阅读 · 2 评论 -
C++ 重复释放同一块内存空间没有报错的思考
是因为重复使用delete删除相同的内存空间,但编译器竟然没有报错,所以开始了一系列关于内存空间的尝试和思考。1. 内存空间被释放,不代表存储的内容被删除。一块内存被delete后,只是从是否可以被再次分配的意义上进行了释放,其中原先存储的内容不会立刻被抹除。可以简单写代码验证如下:int main(){ int *a1 = new int(3); cout << "*a1 = " << *a1 << endl; delete a1原创 2021-05-12 15:47:29 · 4485 阅读 · 14 评论 -
C++ 定义返回数组的函数
Key最近遇到的一个问题是写C++的时候想要函数的返回值为一个数组,所以在定义函数返回值的类型的时候使用了指针。但是这时候返回的不能是在函数内部定义的数组首地址,因为这个地址在函数执行完成之后就会删除,导致调用这个函数的其他函数不能得到这个返回的数组。后来发现可以借用new及其初始化解决这个问题,在函数内部不定义返回的地址,而是直接在return后面new一个新的区域储存需要返回的内容。这里需要...原创 2019-05-20 05:43:54 · 13834 阅读 · 2 评论 -
C++ set和map的用法
知识点小结最近刚刚把算法中的排序部分刷完,由此觉得在实际的应用中应该不会每次都要手写排序,于是查到了一些关于容器的知识。这里先小结一下set和map。这两个容器属于关联容器,底层实现是红黑树,有点类似于java中的hashmap。set只有键,而map同时拥有键和值。同时,set和map这两个关联容器还有自己的函数,如insert和erase等。还是先从简单的部分理解,目前我的最大感受是,如果...原创 2019-05-26 21:52:32 · 980 阅读 · 0 评论 -
C++ 关于结构体与类的使用,以及“.”和“->”的使用
知识点小结之前定义链表的的时候都是拿结构体来定义的,然后声明的时候就自然声明成了指针。于是所有访问结构体内部成员变量的时候都用的“->”符号。其实在声明的时候是可以不用声明成指针的,继而可以使用“.”符号来访问成员变量。对于C++来说,关键在于分清楚使用结构体时,什么时候适合声明成指针,什么时候适合不声明成指针。如果是定义链表这样内部成员变量包含指针的结构体,则声明时最好声明称指针,如果...原创 2019-06-14 04:07:55 · 2099 阅读 · 0 评论 -
C++ 指针与取地址&
知识点小结C++相比于其他的语言,比较有特点的就是指针的内容。因为涉及到内存地址和地址当中的存储内容,比较容易混淆。其中的关键点是,当我们定义一个指针p,比如说int *p时,指针p必须指向一个地址,而*p则表示该地址中包含的内容。指针p是不能直接指向一个内容或者变量的,这个说法可能不是那么准确,但后续其他复杂的例子稍后再说。就基本情况而言,记住指针p一定要指向内容的地址而非内容,一定要指向变...原创 2019-06-09 03:29:34 · 14838 阅读 · 1 评论 -
C++ 关于对复杂数据类型排序的比较器
知识点小结对于排序问题,我们可以自己写基于不同原理的排序方法,如冒泡排序,快排等。但在实际应用中,我们不可能每次都自己写排序,这里我们可以C++在algorithm包中定义好的sort()函数进行排序。但是,不论我们是自己手写排序,还是使用已有的sort函数,在面对复杂的数据类型,比如自己定义的结构体时,我们就有必要自己定义一个比较器,否则无法进行排序。对于sort()函数来说,其默认是按升序...原创 2019-06-09 04:22:08 · 781 阅读 · 0 评论 -
C++ STL典型容器queue,vector,stack的使用方法
知识点小结:在使用c++已有的容器时,虽然queue,vector和stack一些基本操作都是类似的,但因为其函数名称不同,比如返回首元素有的是用front,有的是用top。没有整理经常混乱,下面对这几种典型类型的基本操作函数进行一下小结。首先是stack的操作,基本操作有压入push(),弹出pop(),返回首元素top(),返回大小size(),判断是否为空empty()。#in...原创 2019-06-16 23:49:10 · 4175 阅读 · 0 评论 -
C++ 自定义函数返回类型
知识点小结C++的基本数据类型限制了函数的返回类型,其不像python一样可以直接返回一个list,list里面可以包含多个想要返回的内容。为了能够让C++的函数返回类型也可以不受数量上限制,我们可以先定义一个我们希望的数据类型的类或者结构体。如果使用类的话,该类当中只包含成员变量和构造函数。下面我们定义一个同时返回一个数字和一个字符串的数据类型。具体代码如下:#include <...原创 2019-06-29 00:11:06 · 6395 阅读 · 3 评论 -
C++ 整型与字符串类型的互相转化
知识点小结多年前对类型转化这个概念的认知停留在可以强制类型转化上,最近在整型和字符串类型互相转化的时候才发现原来说的不是一回事。下面提供我对这个知识点的小结。整型向字符串类型转化需要借助sstream头文件,而字符串向整型转化需要借助stdlib.h头文件,具体的过程如下。#include <iostream>#include <string>#include...原创 2019-06-29 03:03:24 · 401 阅读 · 0 评论 -
C++ const和&在函数参数中的含义
知识点小结C++中有的函数参数会用const来传递,同时配合&取地址符一起使用,形式如 void form(const int &a)。一开始并不懂其中深意,后来查了一下,发现这种用法和值传递的效果是一样的。但是因为引用的效率较高,所以在参数是复杂的数据类型的时候,采用这种常量引用的方法。这样既使用了引用,又使用const限制了对参数的修改。具体代码如下图所示:#inc...原创 2019-06-29 03:33:19 · 9743 阅读 · 1 评论 -
C++使用默认堆结构并进行排序
知识点小结在使用C++时,遇到需要排序的情况我们不能总是手写排序,有的时候我们会借助堆结构来进行。但是需要注意的是,C++默认的堆结构是大根堆,而且push进堆结构的数据一定是能够比较的。C++中的堆类型是放在头文件<queue>中的,调用大根堆的方法是priority_queue<数据类型> 名称。如果是无法默认比较的数据类型,就需要自定义比较器或者在结构体内部定义比...原创 2019-07-05 18:34:18 · 547 阅读 · 2 评论 -
C++ new的用法
知识点小结:new其实就是告诉计算机开辟一段新的空间,但是和一般的声明不同的是,new开辟的空间在堆上,而一般声明的变量存放在栈上。通常来说,当在局部函数中new出一段新的空间,该段空间在局部函数调用结束后仍然能够使用,可以用来向主函数传递参数。另外需要注意的是,new的使用格式,new出来的是一段空间的首地址。所以一般需要用指针来存放这段地址。具体的代码如下:#include <...原创 2019-07-18 20:40:39 · 242269 阅读 · 29 评论 -
C++ 结构体指针与结构体数组的赋值
知识点小结:当需要批量赋值结构体的时候,可以使用结构体数组。对于结构体指针,可以用来指向结构体数组的首地址,但是不能按照结构体数组的赋值方式进行赋值,感觉是无法预知后面批量赋值的大小。具体情况见以下代码:#include <iostream>using namespace std;struct student{ string name; int score;...原创 2019-07-18 22:15:39 · 14167 阅读 · 0 评论 -
C++生成随机数的方法
知识点这个问题的关键是明确伪随机数的概念,计算机生成的随机数都是伪随机数。简单来说这个伪随机数需要依靠一个种子来决定这个数值的大小。默认情况下,这个种子的值是1。这造成了如果不改变种子的值,我们生成的随机数就会是同一个值。因此,我们需要在每次执行生成随机数的代码时,改变种子的值,而计算机的当下系统时间就是非常好的选择。具体情况看下面简单的代码:#include <iostream>...原创 2019-05-20 03:43:57 · 12010 阅读 · 1 评论