自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

见牛羊的博客

做个快乐的人

  • 博客(63)
  • 资源 (3)
  • 收藏
  • 关注

原创 《C++并发编程实战》精读总结:第四章 并发操作的同步

之前我们实现的是对公共数据的保护,但是线程之间几乎没有其他任何的交互操作。像“某线程需要等待另一线程完成后,才能开始执行”这种行为,我们通常称为线程的同步。本章主要是来展示线程是如何进行同步(交互)的。

2025-03-14 17:36:15 273

原创 《C++并发编程实战》精读总结:第三章 在线程间共享数据

多线程数据共享的问题多是由于对数据的改动引起的,要对共享的数据进行保护,比较直接的方法就是实用互斥和加锁。下面看一个简单的例子,使用到了互斥mutex,和对互斥加锁lock_guard<>。这里,假设一个线程调用add向stack1里添加元素时,如果另外一个线程调用top_value想要看stack顶部的元素是无法做到的,因为add已经锁住了互斥mutex1。注意,互斥标记的是代码。锁住互斥就是锁住标记代码涉及到的共享数据。

2025-03-06 18:57:56 134

原创 《C++并发编程实战》精读总结:第二章 线程管控

传递进线程的unique_ptr会以副本的形式被复制到线程的空间中,这与智能存在唯一一个unique_ptr指向对象冲突,刚刚的任务是最简单的一种,是一个普通函数,返回为空,也不接收参数。复杂一些的任务就不能用简单的函数表示了,可以用函数对象,函数指针,lambda表达式等。其实上面的代码中,我们已经在给线程中的任务(函数)传递参数了,但是目前为止我们并没有发现给线程上的函数传递参数有什么不同,而这恰恰是在线程上写代码的一个特殊之处,所以这里单独分一个标题来讲。以最简单的任务,一个空函数为例。

2025-02-28 17:02:35 709

原创 《C++并发编程实战》精读总结:第一章 你好,C++并发世界

第一章通常来说比较轻松,注意一些概念性的表述即可。

2025-02-25 15:36:37 419

原创 《Effective C++》精读总结 — 3. 尽可能使用const

第一次是为了顺利调用const成员函数,将this将至转换成const类型(因为如果默认调用non-const成员函数,说明调用函数的对象是non-const的),否则就会递归调用non-const成员函数自己。另外,如果const成员函数的返回值也有const修饰,则需要借助const_cast<int>做第二次类型转换,目的是将返回的结果中的const移除,如上面代码中被注释掉的地方。这里注意最后,我们为了重复使用const成员函数的逻辑,其实是直接返回了const成员函数,但是做了一次类型转换。

2025-02-21 14:52:16 473

原创 ROS使用Rviz画图的方法2——不使用catkin

但是往往实际应用中我们是既有的C++工程,并不是完全基于ROS构建的,那么就可以借助CMakeLists来调用ROS的库,直接使用C++的编译器来进行编译,也能够完成在Rviz中显示的目的。在上一篇介绍了如何使用ROS的Rviz来显示我们想要的图形,整个编译的环境还是借助了catkin完成的,可以参考(这种方法比较适用在将ROS融入到现有的工程中。就能够在Rviz中有相同的显示效果。

2025-02-11 13:34:50 240

原创 ROS使用Rviz画图的方法

目录1. 事例代码2. 发送框架及内容分析3. rviz中显示效果及设置4. 关于ros信号建立先后的补充在一些需要可视化的任务重,我们通常会借助ROS里的Rviz来进行,比如自动驾驶调试的车辆显示。本篇以一个简单的例子,介绍如何使用ROS在Rviz中进行显示。先看完整代码:2. 发送框架及内容分析先关注main函数的部分,想要在rviz中显示,需要四个基本步骤:有了上面的基本框架,就可以填充消息内容了,在第三步创建消息发布者时,对消息的类型和使用的话题进行了定义,定义类型为visualizati

2025-02-11 10:47:09 819

原创 CMakeLists 写法总结2.0

上述代码中PLATFORM是由于我们想提供交叉编译的可能,所以将其定义在最上层的CMakeLists中,并且在后续代码中,通过if判断,来设定不同的编译处理器,分别对x86和arm的平台增加不同的编译选项。在app文件夹下的子层CMakeLists逻辑就简单很多,主要是根据平台的不同,选择不同的子文件夹路径,这里对同一个平台,比如x86平台想编译不同功能的主函数入口,也可以从这里进行分支,主要就是找到对应平台及功能主函数的路径下的底层CMakeLists.txt。

2025-02-10 15:41:12 1039

原创 《Effective C++》精读总结 — 2. 尽量以const,enum,inline替换#define

文中说这个条款也可以改成“尽量以编译器替换预处理器”,个人觉得这句话主要是说编译器是方便对代码本身进行调试的,但是预处理器其实和代码的逻辑无关,如果程序报错是很难排查的。所以尽量减少在预处理阶段的操作。宏定义常量可以替换为const常量,这样做即能够统一管理,还增加了类型检查等宏定义无法实现的优点。最后,#define的需求降低了,但是#include和#ifdef/#ifndef仍然很重要,所以预处理器的工作不能完全替代。

2025-01-17 17:07:01 622

原创 《Effective C++》精读总结 — 1.视C++为一个语言联邦

C中进行值传递效率会更高(往往是内置的数据类型),而object-oriented和template中因为涉及到自定义的构造和析构,通常通过引用+const的方式进行传递效率会更高。而到了STL中,迭代器和函数对象都是在C指针上塑造出来的,所以值传递又再次变得更加适用。第一个条款是一个很好的对C++总体认识的说明,我们接触C++的时候往往只是在其中一个领域深耕,而忽略了。C++ 包含4层语言体系,

2025-01-13 19:30:18 163

原创 Python获取命令行参数

在写python程序的时候,经常需要获取命令行的参数,以达到灵活配置和批量执行(结合配置文件和sh脚本)的目的。下面介绍两种方法,一种适合简单的参数输入,一种适合更多更专业的参数输入。

2025-01-03 16:58:30 588

原创 旋转矩阵乘法,自动驾驶中的点及坐标系变换推导

CA(1,1)向量经过逆时针旋转90°,得到CB向量(-1,1),向量的旋转矩阵不存在坐标系的变换,不用在意上面的定义,直接用点左乘具体的旋转矩阵即可。我们将原坐标系逆时针旋转90°,得到DBE坐标,其中BD为x轴,BE为y轴,在DBE坐标系中(以坐标系G'),A点在G’坐标系中的坐标表示为A'(1,-2)。关于旋转变换,离不开矩阵的乘法,而矩阵乘法的物理意义和本身数学上矩阵乘法的内向相消决定了乘法的顺序,在CBD坐标系中(以坐标系G代表),其中BC为x轴,BD为y轴,A点的坐标为(2,1)

2024-09-20 16:53:13 1266

原创 回调函数的使用详解

把我们自定义的函数注册到一个全局函数指针的变量中,然后在程序需要用到的时候,调用它。

2024-06-26 17:20:37 948

原创 Gflags的使用

在实际工程代码开发中,发现gflags很好用,可以在运行。

2024-06-21 16:38:32 735

原创 如何用Shell写一个启动脚本

通常情况下,我们在Linux下运行一个编译好的程序,只需要在可执行文件的路径下直接运行即可。但随着程序变得复杂,编译选项的增多,使用库的增加以及对可执行程序输入的参数变多,直接执行的过程变得比较麻烦。这时可以写一个启动的脚本来一键拉起程序。下面我们来看下如何用shell来创建一个拉起程序的脚本。

2024-05-28 17:22:39 828

原创 Python 多进程和多线程在加速程序运行上的差别

IO密集型指的是系统运作大部分的情况是CPU在等 I/O(硬盘/内存/网络等等)的读/写操作,这时候CPU的占用率是非常低的(这也是多进程加速表现不明显的原因)。起因是在处理一个需要大量计算且批量生成文件的程序时,使用多线程的方法处理计算任务加速效果不理想,后来采用了多进程的方式加速效果很好,所以花点时间探究一下两者之间的区别。对于IO密集型,CPU占用率低,一个任务执行后需要CPU一直等待,如果使用多线程对程序进行并发执行,那么CPU在原本等待的时间就可以执行其他任务,进而加速程序的执行。

2024-05-08 09:54:32 510 1

原创 将double类型转为两个float类型存储(顺带看看初版到最终版的优化思路)

实际工作中碰到一个需求,将一个double类型的变量,存储成两个float类型。最后再根据两个float类型转回double类型。因为实际的信号列表已经定义了好了两个float类型,所以只能以这种折中的方法将double类型存储下来。

2024-03-30 10:57:21 542

原创 C++ 关键字小结

delete 的作用和=default 有点相反,是显式的表示不用某个默认的函数。比如,有时候我们不想使用默认的拷贝构造函数,就可以写如下的代码。比如,用户如果写了自己的构造函数,那么编译器就不会创造默认的构造函数了,这有可能会带来编译错误。在执行A a3 = a1;=default 一般会放在默认的构造函数,析构函数,拷贝构造函数,拷贝赋值函数,

2024-02-14 21:31:07 218

原创 shared_ptr放入vector,要及时clear,避免内存泄漏

最近碰到一个内存泄漏的问题,查了半天发现是vector数组的成员中有共享指针,而vector没有释放引用计数导致的。可以看到,因为使用了vector而没有清空,增加了智能指针的引用次数,但是在使用完vector之后没有释放,到时计数没有回归。我们看看嵌套一个结构体,结构体里也有一个共享指针会如何。这里我们来引深一下,为什么放入Vector之后,

2024-02-14 18:54:55 1969

原创 卡尔曼滤波详解(1)

更新部分的三个公式来源,实际上是由两个正态分布的公式相乘的结果得到的。根据预测部分的结果,我们得到了预测的当前时刻的状态量,这个状态量其实服从高斯分布。同时,在当前时刻,我们有当前时刻的观测量,这个量也服从高斯分布。更新部分的主要操作,就是将这两个高斯分布的量结合,得到一个方差更小的高斯分布。图示如下(这个图是来自。

2024-02-12 20:50:38 2555

原创 C++单例模式详解

起因是在程序中重复声明了一个单例模式的变量,后来程序怎么调都不对,最后发现变量是用单例模式,修改是全局的,所以决定好好梳理一下单例模式。首先,为什么要用单例模式,就是因为我们希望一个类只有唯一一个实例,并且提供一个全局的访问点。从这个描述不难看出,这个实例应该是要static来修饰的。。

2024-02-05 16:44:08 2665

原创 ASAN 内存问题检查工具

ASAN可以定位的内存问题有:内存越界(堆内存越界,栈内存越界,全局变量越界),内存释放后使用,读取未初始化内存,内存泄漏。

2023-09-22 16:41:37 842

原创 C++:constexpr 和 const 的区别

constexpr 是 C++ 11 标准新添加的关键字,原先的标准中是只有const关键字的,作用是表示只读常量。但是,其实只读常量是两个属性,分为只读和常量,都用const来表示会产生歧义。这里补充const的一个重要概念就是,const后面的变量,仅仅表示不能通过该变量改变背后实际的值,但是如果其他变量也能够表示同一块内存空间,这个内存空间里的值是可以通过其他变量来改变的。上面的程序做如下修改,arr2就可以正常的编译,因为传入的是一个constexpr代表的常量类型。

2023-09-18 19:10:07 453

原创 小记录:tcpdump的常用命令

基本的抓包命令, 从eth0 抓取,保存到xxx.pcap。# 可以按照协议抓取,如udp,ip,arp等。# 抓取源ip 或目的 ip的包。# 抓取多个源ip的包。

2023-09-11 15:52:01 736

原创 旋转矩阵左右乘,弄清变换关系更重要

关于矩阵左乘和右乘的区别,看了不少数学解释,大概是我水平不够,不是很懂的样子。但本来我也是做应用,抛开理论不谈,看看左乘的实际的使用情况。这个非常的重要,如果没有定义好矩阵下标和坐标系之间变化的关系,就会彻底陷入混乱。但实际上我们是把上述坐标系的变换定义为左乘的,这比较符合我们的阅读习惯。先不考虑左乘还是右乘,对于矩阵乘法来说,是遵循内项相消的。这里,如果我们有坐标系3到坐标系2的矩阵变换关系。,就可以得到坐标系3转到坐标系1的变换矩阵了,即。,以及坐标系2到坐标系1的矩阵变换关系。就是说,我们是先有了。

2023-09-06 20:03:48 1813 7

原创 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 892

原创 Yaml配置文件读取方法

另外,上面提到的类型问题,在这里用.as来体现,将对应的配置文件中的值,读入成程序中期望得到的值的类型,这里test_name希望读入为string。在日常的代码中,有一些值是配置文件中定义的,这些值可以根据用户的要求进行调整和改变。这样开放程序给用户时,就可以不必开放对应的源码,只开放yaml格式的配置文件即可。但是读入之后,其实是有对应需要的类型的,比如is_debug读入后需要时bool类型,test_time读入之后需要是int类型。我们先写一个简单的配置文件,然后将其中的值读入到程序中。

2023-08-24 17:21:52 1061

原创 C++ 编译告警: delete called on that is abstract but has non-virtual destructor

上述告警在使用arm编译器编译的时候报出,意思是缺少虚的析构函数,在delete被调用的时候,会造成问题。典型的就是内存泄漏。看例子:、1. 正常情况上面代码中的两个类,一个是基类Base,一个是继承Base的子类Child。按照正常的声明方式,调用运行。这是最正常的情况,声明了一个子类,首先会调用父类的构造函数,然后调用子类的构造函数。析构时先调用子类的析构函数,再调用父类的析构函数。

2023-07-06 17:53:12 1138

原创 C++结构体内有指针,直接赋值报Segmentation fault原因分析

最近写程序的时候,用了别人定义好的结构体,结构体的成员变量包含指针,直接赋值后运行报段错误。下面对这个问题进行一下分析。

2023-06-08 19:19:21 1657

原创 CMakeLists 写法总结1.0

之前简单介绍了makefile的写法,但实际工程中基本不会手写makefile,通常情况是会写一个CMakeLists甚至是多层多个CMakeLists来构建整个工程。关于makefile和CMakeLists的关系:make命令实际上是按照makefile中的内容来执行的,而CMakeLists就是用来生成makefile的,是cmake命令按照CMakeLists中的内容生成makefile文件。

2023-04-08 22:17:56 3287 1

原创 Eigen::Matrix的6个模板参数含义

Eigen Matrix 模板参数解释

2023-03-20 19:26:04 535

原创 git入门实用技巧

git入门实用技巧

2023-03-12 22:58:54 444 1

原创 C++面经总结1——类相关

C++面经自己整理,按主题发出,本偏主要和类相关

2022-11-13 19:28:31 522

原创 Linux定时器2

1. POSIX定义的定时器有了上一篇关于setitimer定时器的介绍,相信Linux下定时器的用法已经有了基本了解。我个人在使用setitimer定时器的时候,有一个非常头疼的问题,就是setitimer定时器不能设置多个。严格意义上讲,setitimer定时器只能按照时间处理的类别,分别设置三种定时器,即ITIMER_REAL,ITIMER_VIRTUAL和ITIMER_PROF三类,具体解释见上一篇博客。但这非常限制Linux下定时器的使用。解决方法,就是用POSIX下定义的定时器。可以把P

2021-11-26 15:02:40 2199

原创 Linux定时器1

目录1.itimerval-定时器的基本时间单元2.setitimer——创建定时器3.简单实例1.itimerval-定时器的基本时间单元首先要理解itimerval结构体,这是组成定时器的基本时间单元。关于timeval结构体,上一篇博客有讲到,是由秒时间和微秒时间组成的。这里it_interval表示的是一个timeval类型的时间,这个时间是创建的定时器的周期性。即如果这一时间设置为5s,则该定时器每5s触发一次。Itvalue也是timeval类型的时间,表示首次倒计时时距离定

2021-11-17 18:37:28 775

原创 Linux下有关时间的函数:time,times,clock,gettimeofday等

因为项目需要,所以把Linux和windows下时间及计时器相关的内容都刷了一遍。终于抽出时间总结一下。目录1. 时间的概念2. 获得时钟时间的函数2.1 时钟时间的存储类型2.2 time函数2.3 gettimeofday函数3. 获得程序运行的时间(即进程时间)3.1 进程时间的存储类型3.2 times函数3.3 clock函数4. 补充说明1. 时间的概念首先理解时钟时间,也叫做墙上时钟时间,可以简单理解为宏观上经过的时间。细究起来就是进程运行的

2021-10-14 14:19:58 6111

原创 Linux使用gcc生成与使用动态库与静态库

1. 动态库与静态库的区别能够自己生成库文件并使用自己的库文件,对理解一个大型的工程以及模块开发是很有好处的。事实上,我们进行模块开发的时候,往往是接触不到主程序的,开发的模块通常都是打包成库文件供他人使用的。库文件分为动态库与静态库,动态库一般是以.so为结尾的文件,静态库一般以.a为结尾。动态库和静态库在编译过程中的区别是在链接的时间,动态库是在程序执行的时候被链接的,而静态库是在编译过程的链接阶段被链接的。这意味着,使用动态库时,库必须和可执行程序同时存在,不能被删除。而使用静态库时,在链..

2021-09-02 19:42:56 351

原创 C++编译过程详述

想总结一下这个问题是我突然有一天好奇编译头文件和编译头文件对应的源文件有没有区别,因为写makefile的时候依赖即可以写头文件,又可以写源文件。在网上查了半天,估计我的这个问题比较stupid,也没有明确的回答。索性顺藤摸瓜看了看C++的编译过程,虽然之前大致有个了解,但不够仔细。这一看发现,区别肯定是有的(尽量编译源文件而不要尝试编译源文件对应的头文件)。但更重要的是,把编译过程清楚捋一遍,解释了我之前不少的疑惑。而学c++的时候上手就是vc6.0,对理解编译过程太不友好。所以还是应该有个全面的认识。(

2021-08-11 12:57:25 711

原创 前置递增运算符(++)比后置递增运算符效率高的原因

前置递增运算符比后置递增运算符效率高,当然递减运算符也是一样的。我一开始是不理解这句话,而且在接触程序之初,似乎更习惯用后置的情况,即经常会写成i++。前置的形式是返回递增或递减之后的对象,只需要返回该对象的引用。而后置的形式返回的是递增或递减之前的对象,因此需要额外创建一个对象副本,返回的不是引用,而是这个副本对象。虽然有点抽象,但是上面这段话可以说就是标题的回答了。下面把上面这段回答翻译成人话,啊,不,翻译的直观一点~。从两个方面来说明,使用效果上和实现方法上。使用效果上。对于++i和i+

2021-08-08 17:27:36 827

原创 C++ STL 迭代器用法总结

最近写东西用到了unordered_map容器,然后想要逆向遍历一遍哈希表,结果报错。研究了一下发现STL中不同容器对应的迭代器有很大的区别。关于迭代器,之前一贯粗浅地按指针来理解了,借此机会详细总结一下。1. 迭代器说明迭代器的作用是介于容器和算法之间,迭代器大致分为5类:随机访问迭代器,单向迭代器,双向迭代器,输入迭代器,输出迭代器。其中主要使用的,也是最重要的是前三种。随机访问迭代器:支持通过偏移量访问,比如it+5。单向迭代器:一般都是正向,仅支持++操作,不支持—操作,不支持偏移量

2021-08-07 15:12:42 666

visial studio2019缺少的MsBuild文件

visual studio 2019 配置opencv时会出现找不到Microsoft.Cpp.x64.user的情况,是缺少相应的MsBuild文件导致的

2020-11-02

armv7交叉编译工具.rar

这是armv7的交叉编译工具,我用来在rk3288的板卡上进行交叉编译时用的。是在linaro的官网上下载的,2018版的,很好用。

2020-10-18

armv8-Liunx交叉编译工具.rar

2019armv8交叉编译工具,个人用于rk3399的交叉编译,是64位的linux系统。是我从官网上下载的。国内的网络下载很慢,这里分享给大家,亲测可用。

2020-10-18

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除