- 博客(63)
- 资源 (1)
- 收藏
- 关注
原创 基于类型属性的重载
在一个泛型算法中引入更为特化的变体,这种设计和优化方式称为算法特化。基于函数模板的部分排序规则,上述两个例子,都是第二种函数模板为更加特化的模板。存在更为特化的函数模板时,编译器会优先选择这类函数模板,只有其不适用时,编译器才会回退到更为泛化的版本。因此,我们需要用到其他技术,更好的实现算法特化。
2025-03-28 13:19:38
741
原创 萃取的实现(二)
SFINAE(Substitution Failure Is Not An Error):替换失败不是错误。该技术在模板参数推断过程中,将构造无效类型和表达式的潜在错误,转换为简单的推断错误,允许重载解析继续在其他待选项中间做选择。中的解释如下:在函数模板的重载决议中会应用此规则:当模板形参在替换成或失败时,从重载集中丢弃这个特化,而非导致编译失败。SFINAE除了用来避免与函数模板重载的相关为的误,还可以在编译期间用来判断特定类型和表达式的有效性。
2025-01-10 17:06:24
943
原创 萃取的实现(一)
name所有元素之和为负值,很明显是和超出了char所能表示的范围。所以对数组求和,和的数据类型的表示范围要大于数组的数据类型的表示范围。因此源码中total的类型不能是T。
2024-10-16 14:01:42
949
原创 C++泛型库
一些库包含这样一些接口,调用方可以向该类接口传递一些实体,并要求该实体必须被调用。这种编程方式称为,调用方传入的实体称为。以上这些类型统称为,其对应的值称为。
2024-09-02 17:03:00
1149
原创 模板基础术语
声明指将名称(变量,函数,类或结构体)引入或再次引入到一个作用域内。声明包含名称的一部分类别,但不需要其太多细节信息。class C;定义对于变量,函数,类或结构体是不一样的。对于变量,如果进行了初始化,或者未使用extern,声明就变成了定义。如果进行了初始化,即便使用extern修饰,也属于定义,但会触发警告“'extern' variable has an initializer [-Wextern-initializer]”
2024-08-09 13:12:25
333
原创 编译期计算
编译时会报错“No matching function for call to 'print' ”,因为print模板不会生成参数为0的函数,当编译迭代到...args为0时,发现没有合适的函数调用报错。语句,编译时,整个函数的所有语句都会被编译,当类型为string时,由于不支持和整型的比较,及-和*操作符,arg == 1和arg * factorial(arg - 1)都会报错。使用编译器if判断参数数量,当参数为0时,不再执行任何语句,解除对void print(void)函数的依赖。
2024-07-23 17:29:56
746
原创 按值传递还是按引用传递
从 C++11 开始,可以让调用者自行决定向函数模板传递参数的方式。执行过程中,会发现sum并没有按引用传递,而是按值传递。很明显,这不符合预期。
2024-05-10 14:23:41
493
原创 std::invoke解析
std::invoke是c++17标准库引入的一个函数模板。这个函数模板能做什么?原理是什么?先来看一个简单的例子,回答std::invoke“能做什么”。通过上面的例子,可以看出,std::invoke仅仅是对函数指针的调用做了一下封装,这种技术被称作。单从上面的例子来看,std::invoke的存在没有任何意义:直接调用函数更加方便,效率也更高,而通过std::invoke调用并不能带来任何收益。在这个例子中,std::invoke似乎不可取代。
2024-05-07 14:54:09
1135
2
原创 移动语义和enable_if<>
c++11引入了一个新的模板函数——std::forward,用于实现完美转发,即强制参数以右值形式转发。为什么要引入这样一个模板?当执行g(X())和g(std::move(x))时,g(X &&x)理想地情况下是调用f(X &&x),但实际上却调用了f(X &x)。之所以会这样,是因为C++编译过程中发生了(关于这一概念,可以参考通过使用std::forward,可以消除std::forward的实现。
2024-04-19 18:32:38
525
原创 libevent解析GET参数
使用libevent解析get请求参数,一定要注意一个问题,即调用evhttp_parse_query后,一定要调用evhttp_clear_headers释放结果,否则会产生内存泄漏。关于如果通过libevent写一个http服务参看《
2024-03-30 22:48:12
216
原创 C++模板基础技巧
当提到typename关键字时,首先想到的便是和class关键字一样,定义模板时引入一个模板参数,但除此之外,typename关键字还拥有另外一个功能——消除歧义:指明模板内部的一个标识符代表的一种类型,而不是一个静态成员,例如:typename T::SubType * ptr表示定义一个类型为T::SubType的指针变量,而不是T类型的静态成员变量和ptr相乘。错误的意思是“为什么必需要使用typename关键字?这与模板的编译机制有关。
2024-03-30 18:26:46
703
原创 非类型模板参数
通常它们只能是整形常量(包含枚举),指向 objects/functions/members 的指针,objects 或者 functions 的左值引用,或者是 std::nullptr_t (类型是 nullptr)。但是个人始终觉得这个说法有些勉强,非模板类型参数的类型设置为uint64_t,无论10,还是1000,都是用uint64_t,会有什么问题么?非类型模板参数在c++中的使用场景还是比较多的,例如:std::array,std::get(读取std::tuple)。
2024-03-05 14:20:43
366
原创 C++类模板
同C++普通类意向,类模板的成员函数的实现即可以放到类的内部,也可以放到类的外部。这里需要注意两个细节,每个成员函数的实现都必须使用‘template ’来表示这是一个模板,并且::(域操作符)之前使用Array取代Array,来限制使用的类型。如果仔细观察,成员函数的赋值函数的返回值类型必须使用Array,而形参的类型却可以直接使用Array。因为在模板类的内部(包括类的定义,成员函数形参,成员函数体)使用Array等同于Array。
2024-03-02 17:21:41
738
原创 C++函数模板
模板在编译过程中,会进行类型推断,平时使用到隐式类型转换(自动类型转换),在类型推断时,几乎全部失效。通过上面的代码可以看出,模板使用非const引用传参是对变量类型要求最严格的,不允许任何隐式类型转换;模板使用const引用传参允许const类型和非const类型转换;模板使用值传参支持数组到同类型指针的转换,也支持const类型和非const类型的转换。
2024-01-30 20:05:00
979
原创 初识C++模板
尽管源码中仅有一个函数,但却实现了对多种类型的支持。再做一个实验,使用“g++ -S template.cpp -o template.s”生成汇编代码,仔细研究template.s(代码太长,此处不在粘贴),发现可执行程序名称包含max_函数,就是源码中的max_函数。方案二和方案三的本质是一样的,对原有数据类型进行封装,通过回调方式解决数据类型差异问题。从上面的实验推出,名称中包含max_的函数的生成,仅与实例的类型相关,与调用次数无关。实现一个算法:返回两个变量中的较大的一个,并支持不同的数据类型。
2024-01-18 20:11:58
1191
原创 opencv-4.8.0编译及使用
编写cmake时,强烈建议使用find_package引用头文件和lib库,尤其是lib库,千万不要手动逐个引入lib库。opencv的编译总体来说比较简单,但必须记住一点:opencv的版本必须和opencv_contrib的版本保持一致。例如opencv使用4.8.0,opencv_contrib也必须使用4.8.0。注意,一定要下载具体的tag进行编译,不要选择branch,否则编译会报错。进入opencv和opencv_contrib的github页面后,默认看到的是git分支,如4.x。
2024-01-13 23:06:35
1681
原创 gdal获取最小外接矩形
gdal中使用OGREnvelope定义最小外接矩阵,该类通过MinX,MaxX,MinY,MaxY四个成员变量表示矩阵的最小X坐标,最大X坐标,最小Y坐标,最大Y坐标,其形成的外接矩形为{(MinX, MinY), (MinX, MaxY), (MaxX, MaxY), (MaxX, MinY)}。对于点,MinX=MaxX=x,MinY=MaxY=y,所以,对于OGRPoint,调用getEnvelope,返回值为{x, y, x, y}(对应{Minx, MinY, MaxX, MaxY})。
2024-01-09 14:01:29
631
原创 gdal平面几何空间关系
关于平面几何的空间关系判定,gdal提供了8个函数,分别是:Intersects(相交),Equals(相等),Disjoint(不相交),Touches(接触),Crosses(交叉),Within(被包含),Contains(包含),Overlaps(重叠)。关于几种空间关系的概念,网上有许多权威解释,此处不做解释说明。上图给出了一个多边形poly和一组点F,C,G,通过gdal计算poly和F,C,F的空间关系,得出下面两张表(OP表示poly.OP(point*),!
2024-01-06 19:26:25
875
原创 利用std::unique_ptr释放资源
通过unique_ptr的定义(如下),其模板参数有两个 :_Tp为对象的类型;_Dp为对象的释放方法。在unique_ptr对象生命周期结束时,通过调用_Dp释放资源。默认的释放方法为default_delete,是一个仿函数,其通过delete释放指针。FileGuard使用unique_ptr定义了文件句柄自动释放的类型。unique_ptr是stl定义的一种智能指针,利用C++的RAII机制进行内存管理,防止内存泄漏。1.定义一个释放仿函数类型,必须实现operator()(T *ptr)
2023-12-24 18:55:39
763
原创 生产者-消费者C++实现(二)
上面代码实现了生产者——消费者基本功能,由于生产者(proucer_callback)和消费者(consumer_callback)都通过sleep控制了速度,没有出现产品缓冲区为空,而消费者一直循环获取互斥锁(没有产品消费,消费者在空轮,造成cpu资源浪费,影响消费者),而生产者没有机会获取互斥锁的情况,但实际情况不可能通过sleep去控制,这样将会使处理性能大打折扣。第一点需求是显然的,即便是在生产线程和消费线程速率相当的情况下,增加缓冲区也是有益的,这样能够减少生产者抖动(如网络)带来的影响;
2022-11-13 16:47:12
1673
原创 libevent之eventop
功能:IO处理模型架构:实现: event-internal.h定义eventop结构体,在.c文件实例化生成对应的全局对象,如在poll.c中生成pollops对象。event.c中定义eventop对象指针数组eventops,同是在event.c中event_base_new_with_config函数通过策略从eventops指针数组中选出一个对象指针,对event_base的evsel成员指针赋值。 注意,windows的iocp不在该架构...
2022-05-02 22:50:04
414
原创 使用libevent实现简单定时器
功能:使用libevent实现简单定时器,每10s触发一次流程:代码://简单定时器#include <event2/event.h>#include <stdio.h>#include <time.h>#include <assert.h>#include <signal.h>class simple_timer final{public: virtual ~simple_timer(voi..
2022-05-02 18:05:22
997
原创 GDB打印vector指定元素
使用GDB调试程序时,需要查看变量的值。对于普通变量,直接使用p命令即可,如下:对于vector,也可以使用相同的方法,如下:vector元素较少时,这种方法没有问题。但当vector数量上万时,这种方法就不是太方便了:查找自己想看的元素比较困难 有些元素被隐藏,看不到这种情况下,可以通过myvector._M_impl._M_start访问随机访问vector元素,_M_impl._M_start 为vector数据内容首地址,直接使用“p matrix._M_impl._M_..
2022-02-19 14:40:07
1906
原创 Mac系统下VSCode配置gopath
golang程序编译依赖环境变量gopath,并且每个golang项目的gopath不相同。如果通过~/.bash_profile的方法去pei'zhi
2021-06-04 15:52:14
3564
原创 如何查看cpu是否支持sse指令级
Mac:命令:sysctl -a | grep machdep.cpu.features结果:machdep.cpu.features: FPU VME DE PSE TSC MSR PAE MCE CX8 APIC SEP MTRR PGE MCA CMOV PAT PSE36 CLFSH DS ACPI MMX FXSR SSE SSE2 SS HTT TM PBE SSE3 PCLMULQDQ DTES64 MON DSCPL VMX SMX EST TM2 SSSE3 FMA CX16 TP
2021-01-17 22:05:11
4975
原创 服务运维-日志
服务一般情况下运行在后台,没有界面,很难观察到服务的状态。因此,对于服务运维,日志变成了一个非常重要的工具。通过服务日志,可以了解到服务的运行状态,如服务是否正常运行,服务处理了哪些请求,哪些请求被正确的处理,哪些请求处理出现了错误等等。当然,通过linux命令,如top,ps,netstat获取到服务的状态,如服务进程是否存在,服务端口是否打开,通过linux命令获取到的这些信息都是很表面的,只能做到“知其然,不知其所以然”,很明显,这不是我们的目的。服务日志不应该仅仅包含服务的启动,停止信息,这些知
2020-11-26 00:14:14
1399
1
原创 初识valgrind
valgrind是一款非常优秀的性能调优工具,经常使用到的模块主要有下面6个:Memcheck:内存错误检测Cachegrind:缓存和分支预测分析Callgrind:性能分析图Helpgrind:线程错误分析系Missif:堆分析DRD:线程错误分析如果使用valgrind,编译程序是尽量加上-g选项,这样valgrind的输出会包含行号,这样可以帮我们更方便地分析结果。...
2020-11-16 23:45:54
182
原创 程序性能优化之分支预测
程序是由多条指令构成的,程序的运行便是cpu一条一条执行程序指令的过程。一条指令的执行过程大致可以分为加载指令,翻译指令,加载数据,执行运算,更新数据几个阶段,每个阶段都由单独的运算单元去执行。为了提高性能,各阶段是并行执行的,即当前指令的流程到了执行运算阶段,下一条指令的流程有可能已经到了加载数据阶段。这样做至少有两个优点:单元复用和并行执行。即使同一个阶段,多条指令流程也是可以并行执行的,如执行运算阶段,加法运算和乘法运算时可以同时执行的。下图是一张现代cpu运算单元的简单模型(摘自《深入理解计算机系统
2020-11-08 23:14:38
779
原创 程序性能优化工具——gprof
gprof是程序性能分析的一个重要工具,通过gprof工具可以获取程序中函数之间的调用关系,每个函数的调用次数,及函数的消耗时间,从而为程序性能优化指明方向。由此也可以推断出,一个合理的程序设计是相当重要的,很难想象,一个结构杂乱,耦合严重的程序如何进行优化。gprof工具的使用非常简单,下面将对该工具进行简单的介绍。环境:centos7.2,gcc 4.8.5代码gprof_example.c如下:/* * @file gprof_example.c * @brief 统计/etc/au
2020-11-07 19:04:37
651
原创 boost::any实现解析
忘记当初具体想做什么了,只记得要求:将各种类型(如int,char*,float,自定义类型等)放到一个容器里。这样的要求,目前stl的任何容器都是做不到的。因为容器仅仅能够存储同一种类型的对象,因此我们只能往代理的方向去考虑。一提到代理,大家首先想到的可能是继承:设计一个基类(如AnyType),其他的类型均从基类派生(如StringType,IntType,FloatType),容器里存储存储...
2019-11-22 15:36:37
704
转载 CAP 定理的含义
CAP 定理的含义作者:阮一峰日期:2018年7月16日分布式系统(distributed system)正变得越来越重要,大型网站几乎都是分布式的。分布式系统的最大难点,就是各个节点的状态如何同步。CAP 定理是这方面的基本定理,也是理解分布式系统的起点。本文介绍该定理。它其实很好懂,而且是显而易见的。下面的内容主要参考了 Michael Whittaker 的文章。...
2019-11-20 16:12:28
138
原创 使用opencv 4.10报错 "CV_XXX":未声明的标识符
opencv 410全部使用C++接口,将枚举类型的定义全部挪到了命名空间cv内部。当编译报错找不到CV_XXX时,请使用cv::XXX代替。例如“error C2065: “CV_CAP_PROP_FRAME_HEIGHT”: 未声明的标识符”,请使用cv::CAP_PROP_FRAME_HEIGHT代替。“CV_FOURCC”: 找不到标识符,出现该编译错误,请使用cv::VideoWr...
2019-11-18 18:19:20
7078
1
原创 ffmpeg调用avformat_open_input打开rtmp转发流阻塞
G28181协议接入时,为了减少视频处理服务的改动,故采用了rtmp转发的方案。使用nginx搭建rtmp转发服务器,设备代理将流推送给nginx,nginx再将流转发给视频处理服务。但设备代理并不是每次都能够成功推流,如果失败,视频处理服务使用ffmpeg的avformat_open_input会阻塞住,导致整个服务卡死。各种超时设置均无效。经过调试发现avformat_open_inpu...
2019-11-15 19:31:34
2824
2
原创 ffmpeg调用av_read_frame读取实时视频流返回AVERROR_EOF
自己所负责的模块中使用到了ffmpeg,一直都很正常。但最近碰到了个奇怪的问题,使用av_read_frame连续读取摄像头实时视频流,运行一段时间后,该函数会返回AVERROR_EOF,代码如下:void MediaSource::DataProvider::_RecvThread(void){ INFO_LOG(m_LogHandler, "recv thread ENTER, ur...
2019-10-29 18:24:25
11592
13
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人