- 博客(129)
- 收藏
- 关注
原创 C++性能优化常用技巧
如果不需要复杂的哈希函数,仅通过数组下标的形式就能完成哈希,比如key是26个字母或者连续的数字。此时只需要定义一个数组就能实现哈希存储(自定义查找表)。
2025-02-27 20:37:09
901
原创 C++性能优化篇:字符串优化
虽然字符串可以动态扩容,但是每次扩容都会牺牲很大的性能,需要重新申请内存空间,然后将现有的数据拷贝到新的存储上,最后释放旧存储,这个操作非常耗时。通常情况下,我们应该需要预估一个合理的内存空间,然后一开始就分配这么大内存,从而避免频繁的扩容。C++中使用string对象来保存字符串,相较于C语言,它最大的优点就是可以动态扩容,而不需要手动管理内存。当然在带来极大便利的同时,随之而来的也可能是性能瓶颈。常见的性能问题如额外的拷贝、临时对象的生成、频繁的内存释放和分配等。
2025-02-26 11:49:24
278
原创 C++程序崩溃如何定位
对于有调用栈信息(core文件)的情况,我们通常使用gdb来打印堆栈信息,通过堆栈信息基本能够定位异常位置。在linux系统中,程序崩溃时,系统会打印一些log信息,我们可以通过。崩溃时指令地址为55d23e69e60b,减去基地址55d23e69e000,得到偏移地址0x60b。dmesg可以打印崩溃的程序名、进程id、ip(程序出错时的指令地址)地址、基地址、错误信息等。执行编译后的程序,程序会崩溃。表明在main函数里崩溃,并且崩溃的位置也给出来了。如果没有调试信息,则只显示崩溃的函数。
2025-02-24 17:48:29
488
原创 Qt实现登录界面
本文基于Qt实现一个简单的登录界面,主要使用到Widget、button、edit等控件,基于自定义的信号槽实现界面的跳转,使用绘图设备添加背景图等。
2024-09-11 17:54:03
1291
原创 git查看代码提交记录
git log是Git中最常用的命令之一,在某些场景下,我们需要根据一些特定条件来查找,比如:按时间、作者信息、提交记录、修改内容等。简单git log命令就不足以满足我们的需求了。本文将简要描述如何使用这些条件进行查找。按时间查找–after表示查找指定时间之后的提交记录,如:。–before表示查找指定时间之前的提交记录,如:。
2024-09-03 20:49:53
1474
原创 git常用操作大全
1. git diff不接参数,顺序展示多个文件的差异内容(和暂存区内容对比);接参数filename,展示指定文件的差异内容(和暂存区内容对比);接参数–cached,暂存区和本地仓库进行对比。2. git checkout -b [branch_name]创建一个新的本地分支3. git branch -vv查看本地分支的跟踪情况4. git branch -a查看所有分支(包括远程分支)5. git branch -D [branch_name]删除本地分支
2024-08-12 21:46:30
526
原创 如何撤销/回滚远程修改
通过git revert commit_id,撤销指定commit,然后push到远程分支,即可撤销指定commit的修改,并新增一个revert的提交记录。到远程分支,这样对应的历史提交就被删除了。否则就需要解决冲突之后再提交,但是此情况会产生一个新的commit。,不出现冲突的情况下就可以直接。
2024-07-27 13:56:14
660
原创 C++多线程编程之互斥锁
为什么会出现这种情况呢,简单分析下原因,每次加1时,数据都会从内存加载到寄存器,如果taskC某次从内存读到寄存器的值是100,此时失去cpu,taskD也从内存读到100,然后做加1,再写回内存,此时sum的实际值是101,如果此时taskC再次获得cpu,他会计算sum=100+1,sum的值还是101,这就有问题了。这属于数据同步的问题,为了解决这种问题,于是就有了互斥锁。主要有lock、try_lock和unlock三种接口,其中lock失败会阻塞线程,成功则获得锁的所有权。
2024-07-22 18:52:08
370
原创 lock_guard和unique_lock的区别与使用
std::unique_lock具有lock_guard的功能,但同时unique_lock可以使用mutex的接口lock和unlock来主动加锁和释放锁,而lock_guard是不支持的。std::lock_guard 是 C++11 引入的一个模板类,位于 <mutex> 头文件中,用于实现 RAII(Resource Acquisition Is Initialization)模式的锁管理,确保锁的自动获取与释放,即使在异常情况下也能正确释放锁,防止死锁。
2024-07-22 18:51:45
408
原创 设计模式总结
设计模式的目标是管理变化,提高代码复用。在使用模式的时候,应该非常明确需求的变化点与稳定点,否则设计模式不一定适用。另外,设计模式给予我们的只是一个参考,我们更应该关注和掌握的是设计原则,有了对设计原则的深刻理解,在设计代码的过程中,我们也能设计出适合我们自己业务场景的设计模式,这才是学习设计模式最终应该达到的层次。
2024-07-19 19:43:22
1230
原创 C++多线程std::thread使用详解
join代表主线程会阻塞到该线程结束后才会退出,通常情况下配合joinable(是否为可连接状态)使用,因为只有可连接状态的线程才可以调用join。detach模式下需要考虑引用或者指针参数的生命周期问题,在主线程退出之后,它们的资源会被释放,此时子线程有可能访问到无效内存,导致程序崩溃。此时,作为const引用,thread在传递参数的时候,也可以进行值传递,但是考虑性能的情况下,推荐按引用传递。需要注意的是,因为是指针,所以被传递对象的生命周期必须大于线程的生命周期。
2024-07-19 18:37:06
492
原创 C++内存对齐
通常情况下,cpu取数据是按照内存单元取的,而内存单元的地址是对齐的。这就意味着,内存对齐的情况下,cpu取某个地址上的数据(它存储在某个内存单元),只需要取一次即可。这里有一个原则,就是尽量将对齐字节数大的成员声明在前面,从而减少内存对齐时,带来额外的内存开销。c的偏移地址是9,但c要按照2字节对齐,所以要填充一个字节,也就是x所占的位置,因此,c的偏移地址变成了10,可以对齐。对于类或者结构体的对齐,首先考虑内部各变量自身的对齐,其次再考虑类作为一个整体,也需要按照最大的数据成员去对齐。
2024-07-17 23:04:06
509
原创 装饰模式原理与C++实现
动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。装饰模式属于结构型模式,它是作为现有的类的一个包装。通过使用组合而非继承的方式,实现了运行时动态扩展对象功能的能力,并且根据需要可以扩展多个功能,避免继承带来的灵活性差和多子类衍生的问题。装饰类在接口上表现为is-a Component的继承关系,继承了Component的所有接口。但是在实现上,又表现为has-a的组合关系,即装饰类又使用了另一个Componet类。
2024-07-17 22:57:05
832
原创 模板方法原理与C++实现
定义一个操作中的算法骨架(稳定的),而将一些步骤的实现延迟到子类中(变化的)。模板方法使得子类可以复用一个算法的结构,而只改变(重写)这个算法的特定步骤。模板方法是一种非常实用且常见的设计模式,它使用简单的机制(虚函数)为应用程序框架提供了灵活的扩展点。模板方法中被模板方法调用的虚函数可以有具体实现,也可以没有任何实现(纯虚函数),但一般访问权限为protected,因为作为算法的一部分,它没有对外单独开放的必要。
2024-07-15 18:27:04
371
原创 策略模式原理与C++实现
定义一些列算法,把他们一个个封装起来,并且使他们可以相互替换(变化)。该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展、子类化)。Strategy及其子类为组件提供了一系列可重用的算法,使得类型在运行时方便的根据需要在各算法之间切换。策略模式消除了条件判断语句,含有许多条件判断的语句往往可以使用策略模式来解耦合。如果Strategy对象没有数据成员,那么各个上下文之间可以共享同一个Strategy对象,从而节省对象开销。
2024-07-15 18:26:17
526
原创 C++性能优化篇:map与unordered_map的正确使用
在一次代码修改中,我尝试了下使用unordered_map替换map来存储中间结果,发现程序耗时降低了67%,于是仔细分析了下两者的区别。两者都是C++标准库中提供的关联容器,用于存储键值对。,明显降低了复杂度。所以,在不考虑有序性和范围查找的时候,应该使用。简单分析下上述函数的时间复杂度,第一个for循环的时间复杂度为。,在处理大量数据的时候,其效率会更高。,第二个for循环的时间复杂度为。
2024-06-28 08:58:41
595
原创 C++性能优化篇:使用memcpy替代for循环
在做内存数据拷贝的时候,应减少循环,尤其是嵌套循环,多使用memcpy,这样既容易理解,又可以提高程序性能,何乐而不为呢?还有一种提升内存拷贝性能的方式,就是使用并行拷贝的方式。在编写程序的时候,可以考虑使用多个线程,每个线程拷贝其中一段内存。
2024-06-28 08:58:06
1094
原创 C++性能优化篇:深拷贝、浅拷贝与移动构造
在做性能优化的时候,遇到数据量较大的场景,减少不必要的数据拷贝,是可以极大得提高程序性能的。移动语义可以帮助我们实现在浅拷贝的同时,又能避免资源重复释放的问题。但是使用移动语义也要注意,被移动的对象在移动完成之后,不能再被使用,否则可能出现未知错误。
2024-06-26 17:04:37
671
原创 Makefile并行执行
最近在编译项目代码的时候,发现全量编译一次代码需要十分钟,加了多核编译参数之后,还会出现各种错误,导致编译失败。于是我就想改造下makefile文件,使其能够多核编译,经过改造之后,效果显著,8核编译的情况下,只要1分半,编译速度提高了7倍(为之惊奇)。因为依赖关系是c依赖d,那么必须等d执行完,而b又依赖c,就得等c执行完。多核编译的情况下,会并行编译多个cpp文件,从而提高编译效率,并且增量编译也只会编译有修改的cpp文件。,完全没有问题,他会依照d、c、b、a的顺序去执行各个规则。
2024-06-15 00:31:31
1019
原创 git revert的使用
就可以将指定commit id的修改撤销,然后提交此次撤销操作即可。需要注意的是,如果C2处修改的地方在C3或者其他提交节点也有过修改,那么revert就会出现冲突,就需要手动解决冲突后再提交。由于某种原因我们需要撤销掉之前某一次的修改,但是这个修改已经提交,并且后面又经历了好几轮的提交。
2024-04-26 17:37:56
290
原创 在no branch上commit后,再切换到其他分支,找不到no branch分支的修改怎么办?
在no branch上commit后,再切换到其他分支,找不到no branch分支的修改怎么办?
2024-04-26 09:29:40
556
原创 git简单实践
此处就是过滤app、compile.sh、一些中间缓存文件、目标文件等,此时再使用。查看的时候会发现有些文件就是临时文件,不需要提交,你可以创建一个。注意不要添加了不需要提交的文件,
2024-04-17 10:35:07
359
原创 string_view使用详解
std::string_view是C++17引入的一个轻量级、非拥有字符串引用类,它主要用于高效地传递和操作字符串数据,而无需复制字符串本身。
2024-04-15 11:07:27
679
原创 C++17新特性总结
C++17 是继 C++14 之后的一个重要版本,引入了许多新特性和改进,旨在提高编程效率、简化代码以及增强标准库的功能。
2024-04-11 18:01:44
3777
原创 C++14新特性总结
C++14是对C++11标准的一个较小但重要的补充和改进,它在保持向后兼容性的同时,引入了一系列旨在提高代码简洁性和效率的新特性和增强功能。
2024-04-11 16:28:18
2770
原创 std::forward完美转发
C++完美转发是一种利用万能引用和std::forward函数模板来精确传递参数值类别,特别是右值引用和移动语义的能力,从而提升代码效率和资源管理的技术。
2024-04-11 14:43:12
528
原创 右值引用和移动语义
右值引用和移动语义是C++11中用于优化资源管理和提高程序性能的重要工具。它们使得程序能够在保证语义正确的情况下,以较低的成本转移大型对象的所有权,而非进行深度复制,从而显著减少了不必要的内存分配和数据复制,特别是在处理大量数据或昂贵资源时效果尤为明显。
2024-04-11 14:36:09
314
原创 C++11新特性总结
C++11是对C++编程语言的一次重大更新,它引入了大量新特性和改进,旨在提高代码的效率、可读性、安全性以及程序员的生产力。
2024-04-11 14:18:38
497
原创 C++计算程序运行时间
有时候我们需要简单计算下程序的运行时间,但又不想借助工具,而是简单的几行代码来粗略计算下时间,话不多说我们直接开始吧。如果我们多处地方都要计算执行时间,那就要重复去写好几遍这段代码,不太方便。duration的第二个模板参数不写时,即为秒级别时间。
2024-04-10 10:29:46
1138
原创 C++中的string类操作详解
针对C++中的string,本文主要讲解如何对其进行插入、删除、查找、比较、截断、分割以及与数字之间的相互转换等。
2024-04-08 17:44:23
2975
1
原创 STL关联容器之map使用详解
插入数据时,应尽可能的避免额外的构造和析构开销,因此建议选用emplace,而不是insert。但是注意的是,key存在时,insert效率反而更高。删除数据时,目标迭代器就会失效,注意不能再对目标迭代器做任何操作。查找目标key时,为避免二次查找,应使用find方法以提高代码效率。
2024-04-01 19:41:42
1685
1
原创 记录一次数组越界导致的线程死锁问题
pthread_cancel并不一定保证线程被释放,它只是给目标线程发送了一个信号,而只有当目标线程到达一个取消点(系统调用)时,目标线程才会退出。如果需要等待线程退出,应该调用pthread_join来保证这一点。上述代码中,如果在cancel之后调用该函数,程序会出现段错误,因为在使用线程相关的信息时,拿到的是一个空值。在对字符数组进行赋值时,c语言提供的一些函数并不安全,很多时候越界却不自知。
2024-03-28 18:09:15
828
原创 vim设置文本或代码缩进
softtabstop的值不为0时,当按下tab键后,会插入对应数量的空格符,而当其值为0时,则插入的是制表符。为避免在不同环境下打开文本时制表符宽度不一致,可以设置softtabstop。
2024-03-21 15:03:32
299
原创 shell三剑客之sed
作为文本处理的三剑客之一,sed的使用也是非常频繁的,通常适用于对文本中匹配的行或字符串进行替换、删除、添加等处理。i:可选参数,表示对文本直接操作,会修改文本内容,不加该参数则不修改。g:表示替换所有匹配的串,不加则只替换一次。filename:要操作的文件名。str1:表示要替换的目标串。str2:表示替换后的新串。
2024-03-04 18:01:47
230
原创 C++缺陷与思考
很明显,我对C++的思考仅限于C++语言本身,至于其他语言我很少涉及,因此,不能够通过与其他语言的对比中,发现C++更多的不足。因为不知道别人有多好,所以我总以为C++给予我的就是它最好的,但事实上它也有很多缺陷。当然,一切相遇都是最好的安排,既然选择了C++,那它就是最好的,不忘初心(学好C++),方得始终。
2024-02-29 17:58:38
501
1
原创 shell三剑客之grep
作为文本处理的三剑客之一,sed的使用也是非常频繁的,通常适用于对文本中匹配的行或字符串进行替换、删除、添加等处理。i:可选参数,表示对文本直接操作,会修改文本内容,不加该参数则不修改。g:表示替换所有匹配的串,不加则只替换一次。filename:要操作的文件名。str1:表示要替换的目标串。str2:表示替换后的新串。
2024-02-27 18:08:56
222
1
原创 Linux下如何生成coredump文件
在linux下执行程序,当出现coredump时,却发现没有生成core文件,或者生成了core文件却不知道在哪里,下面就讲述如何产出core文件,以及指定core文件的产出格式与路径。上述情况下仅限于个人使用时,修改core文件的产出。但linux作为服务器使用时,则需要更加完整的core文件名,包括时间戳,进程名等等。在当前路径下产出core文件,文件名为core,如果配置了pid后缀,文件名则为core.pid。使得core文件的大小不受限制,能够产出完整的core文件。此命令只会对当前终端有效。
2024-02-27 18:06:55
849
基于gmock实现的cppmockfree的使用方法总结
2023-08-30
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人