
C++
文章平均质量分 80
imred
天下事有难易乎?为之,则难者亦易矣;不为,则易者亦难矣。人之为学有难易乎?学之,则难者亦易矣;不学,则易者亦难矣。
展开
-
Qt:愚蠢的qmake
博主参与了一个使用qmake构建的项目,包含几百个源文件,最近遇到一个恼人的问题:有时仅仅修改了一个.cpp文件,构建项目时就有可能触发全编译。但是编译时又会命中ccache的缓存,这说明源代码实际上内容并没有发生变化。原创 2024-07-21 23:25:54 · 936 阅读 · 1 评论 -
C++:std::function的libc++实现
`std::function`是个有点神奇的模板,无论是普通函数、函数对象、lambda表达式还是`std::bind`的返回值(以上统称为可调用对象),无论可调用对象的实际类型是什么,无论是有状态的还是无状态的,只要它们有相同参数类型和返回值类型,就可以使用同一类型的`std::function`进行存储和调用。这种特性被称作类型擦除原创 2024-06-30 22:36:48 · 1214 阅读 · 0 评论 -
使用OpenGL实现ASCII Art滤镜
效果图:仓库地址:https://github.com/im-red/asciiart_gl之前使用Qt实现过一个CPU版本的ASCII Art滤镜,流程大致如下:根据字体选择确定单元方格大小。将每个可用字符绘制到单元方格大小的空白图片上,计算每个可用字符的平均灰度值。根据第二步计算出来的每个可用字符的平均灰度值,生成一个0~255灰度值到字符的映射表。按单元方格大小对输入图片进行划分,灰度化后求每个方格的平均灰度值。查询灰度值到字符的映射表,对输入图片的每个方格使用字符进行填充。CP原创 2020-10-25 16:47:27 · 356 阅读 · 0 评论 -
Qt:监控一个QObject对象发射的所有信号
如果我们想要监控一个QObject对象发射的所有信号,同时又不追求手段的通用性的话,可以给目标对象的每个信号写一个槽函数,然后手动connect。这听起来就麻烦,有没有不那么麻烦的通用方法呢,自然是有的。如果能对Qt的信号槽原理进行一点深入的探索,我们就能以很简单的方法达到我们的目的。以下代码均基于Qt5.12.7。信号槽的连接保存在sender的metaObject中,其数据结构为QObjectPrivate::Connection:struct Connection{ QObject *原创 2020-10-08 18:08:12 · 2833 阅读 · 0 评论 -
为什么std::priority_queue有一个构造函数接受Compare类型对象作为参数?
在我之前写的一篇博客《使用decltype取函数类型遇到的“invalidly declared function type”问题》中,最近收到一条评论:X: 想问问,既然模板里面已经传入了comp指针了,为什么构造函数里还要再传一次呢?我先把情境描述的更清楚一些,std::priority_queue是优先队列的标准库实现,其声明如下:template< class T, class Container = std::vector<T&g原创 2020-09-08 21:51:35 · 1137 阅读 · 2 评论 -
localhost还是127.0.0.1,这是一个问题(并不是)
(本文内容仅针对Linux环境,内核版本4.15,thrift版本0.11.0,glibc版本2.27)localhost比127.0.0.1快?有江湖传言称,“使用localhost访问本机服务比使用127.0.0.1要快”,这有没有道理呢?自然是没有道理的,除了个别的特例(如https://www.php.net/mysql_connect)因为会对localhost做特殊处理(使用UNIX domain socket替代TCP socket)所以可能快一点(存疑,未验证)外,其他情况使用loca原创 2020-07-29 22:59:27 · 2013 阅读 · 0 评论 -
四种迷宫生成算法的实现和可视化
(上图是使用随机化Prim算法生成一个200x200的迷宫的过程)Github项目地址:maze前言本文中的迷宫指的是最常见的那种迷宫:迷宫整体轮廓是二维矩形,迷宫里的格子是正方形的,格子上下左右各相邻另外一个格子(边和角除外),迷宫内部没有环路,也没有无法到达的格子,起点在一个角(本文中为左上角),终点在另一个角(本文中为右下角),从起点到终点有且仅有一条路径:每个格子都可以抽象成图...原创 2020-04-05 17:29:24 · 17787 阅读 · 1 评论 -
clang:FunctionDecl::isOutOfLine()和FunctionDecl::isInlined()能同时返回true吗?
最近读clang源码时发现这么一段代码:FunctionDecl *FD = ............if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) { ...... if (MD->isOutOfLine() && ......) { ...... if (FD...原创 2020-03-16 00:32:46 · 527 阅读 · 0 评论 -
Qt:为什么QGraphicsView设置Antialiasing/SmoothPixmapTransform没生效?
QGraphicsView::setRenderHint有两个常用的选项:QPainter::Antialiasing和QPainter::SmoothPixmapTransform,前者是用来打开反走样功能,后者用来在对图片进行缩放时启用线性插值算法而不是最邻近算法。然而这两个选项都有一些坑,想达到预期的效果的话得做一些额外的功课。QPainter::Antialiasing和QOpenGLW...原创 2020-03-08 00:37:00 · 2904 阅读 · 0 评论 -
当std::bind遇到非静态类成员函数
之前看项目代码在实现表驱动方法时,经常会遇到这样的代码:// enum { ID0, ID1, ID2 };// std::map<int, std::function<void()>> Foo::m;// void Foo::func0(){}// void Foo::func1(){}// void Foo::func2(){}void Foo::init...原创 2020-02-11 21:32:53 · 1918 阅读 · 0 评论 -
Linux C/C++调试之五:程序运行耗时的组成
分析程序出现的启动缓慢、响应缓慢和操作卡顿等性能问题时,第一步不该是打开代码编辑器浏览我们的代码,而是首先确定问题是否发生在我们的代码中,简单点的方法就是打开top做一个大致的判断,看一看各CPU的us、sy、id耗时的占比都是多少。进一步来讲,我们需要确定时间都花到什么地方了,是我们的代码中?内核中?还是进程睡大觉的地方?现在假设我们的程序运行在一个CPU资源丰富的环境中,因此就不考虑进程争夺C...原创 2020-01-11 23:00:24 · 1768 阅读 · 0 评论 -
条件变量为什么要和互斥量一起使用?
一个简单的使用条件变量的场景:主线程从stdin读取一个字符串,然后由echo线程打印这个字符串,正确的代码是这样的:#include <iostream>#include <condition_variable>#include <mutex>#include <thread>#include <string>#includ...原创 2020-01-02 21:56:01 · 1156 阅读 · 0 评论 -
Linux C/C++调试之二:使用strace追踪程序系统调用
在之前的一篇文章中,我介绍了一种调试手段:利用LD_PRELOAD机制,拦截动态链接器对动态库的符号解析,达到监控程序IO的目的。事实证明我还是太naive了,我们大可利用现成的工具——strace,来更好地完成这一项工作。strace不只能跟踪程序IO,它能跟踪程序的所有系统调用,实现的基本手段是ptrace系统调用,不过实现细节还没研究过,今天只总结一下它的用法。首先用strace来跟踪一...原创 2019-03-02 18:27:42 · 3217 阅读 · 0 评论 -
C++11中静态局部变量初始化的线程安全性
前言大家都知道,在C++11标准中,要求局部静态变量初始化具有线程安全性,所以我们可以很容易实现一个线程安全的单例类:class Foo{public: static Foo *getInstance() { static Foo s_instance; return &s_instance; }private: F...原创 2019-04-07 15:03:31 · 14355 阅读 · 3 评论 -
Myer差分算法(Myer's diff algorithm)
Myer差分算法是一个时间复杂度为O(ND)的diff算法,就以diff两个字符串为例,其中N为两个字符串长度之和,D为两个字符串的差异部分的总长度。这个算法首先发表在An O(ND) Difference Algorithm and Its Variations。Myer差分算法直接解决的问题是最长公共子序列(LCS)的等价问题——最小编辑脚本(SES)问题。当然了,这是论文中的表述,在我看来...原创 2019-04-03 21:51:41 · 4993 阅读 · 0 评论 -
编辑距离算法和Levenshtein距离算法
前言最近在研究diff工具的实现,已经写了一个简单的demo,不过目前这个demo只是把Levenshtein距离算法的结果用Qt可视化了出来而已,还没有实用价值,界面如下:各种diff工具的核心基本都是编辑距离算法,网上许多文章把编辑距离算法等同于Levenshtein距离算法,但实际上Levenshtein距离算法只是各种编辑距离算法其中之一。各种编辑距离算法会使用不同的编辑操作种类,例...原创 2019-03-25 20:53:47 · 1981 阅读 · 0 评论 -
C++:shared_ptr的隐式转换
最近遇到这样一个编译问题,代码是这样的:#include <memory>#include <iostream>class Base{public: virtual ~Base() {}};class Derived : public Base{public: ~Derived() {}};void processSpBase(s...原创 2019-03-22 00:04:03 · 5117 阅读 · 0 评论 -
Qt在Linux下如何查找可用字体
最近遇到一个问题:一个Qt程序在Windows上正常运行,在Linux下编译运行后汉字就全变成方块了,成了名副其实的“方块字”。我一开始考虑是字符编码问题,调用QChar::unicode检查中文字符的编码,发现没有问题。如果不是编码问题,那就需要考虑是字体问题了。然后就安装了文泉驿字体,然后将控件字体设置为文泉驿,发现还是没有用。调用QFontDatabase::families检查所有可...原创 2019-04-09 20:58:13 · 4331 阅读 · 0 评论 -
利用libtooling提取C++中enum值与名的映射
之前的一篇文章中,有思考过如何将enum的值与名进行映射,其中一种方法是利用工具进行预处理生成。最近由于项目中有类似的需求,所以学习了libclang,写了一个小工具实现映射。整体流程非常简单:匹配enum声明的AST节点。获取enum声明AST节点的类型(即枚举类名前面附上作用域)获取enum声明所在文件名(用于过滤系统头文件中的枚举)获取enum声明所在文件行号(可用于区分同一命名...原创 2019-06-04 23:57:16 · 1692 阅读 · 1 评论 -
Qt使用OpenGL进行多线程离屏渲染
基于Qt Widgets的Qt程序,控件的刷新默认情况下都是在UI线程中依次进行的,换言之,各个控件的QWidget::paintEvent方法会在UI线程中串行地被调用。如果某个控件的paintEvent非常耗时(等待数据时间+CPU处理时间+GPU渲染时间),会导致刷新帧率下降,界面的响应速度变慢。假如这个paintEvent耗时的控件没有使用OpenGL渲染,完全使用CPU渲染。这种情况处...原创 2019-07-28 11:58:14 · 16716 阅读 · 28 评论 -
gettimeofday和clock_gettime是不是系统调用?
在《Linux多线程服务端编程》一书5.1节中提到过,在x86-64的Linux上,gettimeofday不是系统调用,不会陷入内核。其实这种说法有点小问题,因为gettimeofday确实是个系统调用,但是linux的vdso(virtual dynamic shared object)机制帮我们做到了在调用这些系统调用时不陷入内核,从而提高了性能。vdso机制说白了就是在用户空间帮我们实现...原创 2019-08-25 16:13:07 · 6370 阅读 · 1 评论 -
使用googletest测试可能断言或导致进程退出的函数
做单元测试,一般是验证函数输出数据与预期是否相符。但是也有例外,我们可能需要验证函数在接收到非法参数时是否会断言或抛异常,例如下面这个例子:int foo(int *p){ assert(p != nullptr); return *p;}当传给foo的实参为nullptr时,运行的预期结果就是断言后进程异常退出。这在单元测试中如何验证呢?如何不让这些验证异常值的用例干扰...原创 2019-08-26 23:41:56 · 2665 阅读 · 0 评论 -
Linux C/C++调试之三:性能分析工具callgrind的使用
callgrind是valgrind工具套件中用于分析程序性能的一个工具,它能够得到粒度为函数、代码行和指令级别的性能数据,具体来说,我们可以得到某个函数、某行代码、某条指令处累计执行了多少条指令。我们看一个实例:// foo.cppint accumulate(int begin, int end){ int result = 0; for (int i = begin;...原创 2019-09-01 21:13:55 · 4079 阅读 · 0 评论 -
Linux C/C++调试之四:callgrind的局限
在上篇文章中我介绍了callgrind的大致用法,可以看出来,callgrind是一个非侵入式的,使用起来也很傻瓜的调优工具。初用时感觉这个工具非常趁手,是个程序都想用callgrind去分析一下。但深入使用后发现,callgrind不是银弹,它还是有一些缺陷的。这些缺陷的根源在于:callgrind使用指令数来衡量性能,而程序员用耗时来衡量性能,指令数与耗时仅仅是一个正相关的关系,而非成比例的关...原创 2019-09-01 23:49:51 · 2010 阅读 · 1 评论 -
Qt实现Trackball交互方式代码
毕设要用到Qt+OpenGL,生成三维模型后需要能够进行拖动旋转等用户交互,因此我实现了Trackball类型的交互代码。Trackball的原理见https://www.khronos.org/opengl/wiki/Object_Mouse_Trackball,在此只做简单介绍。 实现Trackball需要对交互时鼠标的起点和终点进行记录,根据鼠标移动的轨迹改变三维模型旋转矩阵的值,进而实现三原创 2017-04-20 18:02:32 · 1283 阅读 · 0 评论 -
C++的返回值优化(RVO,Return Value Optimization)
前言大家都知道“过早的优化是万恶之源”这句话,然而我相信其中的大多数人都不知道自己是不是在做过早的优化。我也无法准确的定义什么叫做“过早的优化”,但我相信这“过早的优化”要么是得不偿失的,要么干脆是有害无利的。今天我就想举个我认为是“过早的优化”的例子。从函数返回值为了从一个函数得到运行结果,常规的途径有两个:通过返回值和通过传入函数的引用或指针(当然还可以通过全局变量或成员变量,但我觉得这...原创 2018-12-31 22:51:28 · 9896 阅读 · 4 评论 -
QML:使用ListView运行时动态载入Item
想要实现使用ListView运行时动态载入Item,需要两个步骤:动态生成Item将动态生成的Item插入到ListView的model中对于这两个步骤,前者可以使用createComponent和Component.createObject实现,后者可以使用ObjectModel实现,详细内容可见官方文档:http://doc.qt.io/qt-5.9/qml-qtqml-qt.ht...原创 2018-12-16 16:56:14 · 6586 阅读 · 5 评论 -
Qt中QComboBox下拉列表(popup)位置与样式的控制
转载请注明来源:http://blog.youkuaiyun.com/imred Qt中的QComboBox在不同平台下有所差异(主要是不可编辑的QComboBox),如下样式A和样式B: 左边为样式A为“fusion”样式,在ubuntu下的样式似乎就是这个,它的特点是下拉列表会把文字框和箭头盖住。右边样式B为“windowsvista”样式,它是win10下Qt的默认样式,其特点是下拉列表会显示在文原创 2017-10-04 15:18:45 · 41956 阅读 · 12 评论 -
Qt连接MySQL提示“QSqlDatabase: QMYSQL driver not loaded”的解决办法
我使用的Qt版本是Qt5.7.1 msvc2015 64位版,实际上并没有使用MySQL,而是MariaDB,版本为10.2.6。当我运行Qt附带的样例“sqlbrowser”时,总会提示如下信息:QSqlDatabase: QMYSQL driver not loadedQSqlDatabase: available drivers: QSQLITE QMYSQL QMYSQL3 QODBC Q原创 2017-06-26 09:35:03 · 17257 阅读 · 1 评论 -
使用Qt Designer生成的ui文件的几种方式
阅读Qt提供的样例时,看到过好几种使用Qt Designer生成的ui文件的方式,感到有些混乱,所以参考Qt官方文档http://doc.qt.io/qt-5/designer-using-a-ui-file.html进行了整理。 使用ui文件的方式主要分为两类,一类在编译时进行,一类在运行时进行,由于后一类我没有用到过,因此没有进行整理。 假设我们的ui文件为calculatorform.ui原创 2017-06-25 22:11:51 · 4262 阅读 · 0 评论 -
Qt使用connect函数时向slot传递参数:使用lambda表达式
大家可以先看一下我的之前一篇文章:http://blog.youkuaiyun.com/imred/article/details/72940365,这篇是对它的补充,使用lambda表达式这种方法也在https://stackoverflow.com/questions/5153157/passing-an-argument-to-a-slot的回答中。 使用lambda表达式向slot传递特定参数使用的是原创 2017-06-13 16:46:10 · 9612 阅读 · 0 评论 -
学习Qt状态机框架时遇到的一个bug
Qt的状态机框架官方文档(http://doc.qt.io/qt-5/statemachine-api.html)的第一个例子如下:QStateMachine machine;QState *s1 = new QState();QState *s2 = new QState();QState *s3 = new QState();s1->assignProperty(ui->button, "原创 2017-06-09 19:00:40 · 666 阅读 · 0 评论 -
Qt使用connect函数时向slot传递参数
设想这样一种场景:共有5个button,button1~button5,点击button1时输出“button 1 clicked”,点击button2时输出“button 2 clicked”,该如何实现呢? 最粗暴的实现是写5个slot,然后将button与slot分别connect,但这明显会增加许多重复代码,不是一种好的实现。 一种比较好的方式是使用QSignalMapper,它可以接收原创 2017-06-08 22:52:30 · 16143 阅读 · 0 评论 -
QCamera使用QGraphicsVideoItem输出图像
QCamera在官方文档的介绍中提到了3种输出的方式,其中两种比较常规的方式为通过widgets输出和通过QGraphicsView输出。通过widgets输出时使用的是QCameraViewfinder类,而通过QGraphicsView输出时使用的是QGraphicsVideoItem类。 官方文档中仅仅给出了使用QCameraViewfinder类的例子,并没有给出使用QGraphicsVi原创 2017-01-31 14:16:25 · 5736 阅读 · 5 评论 -
前置声明与C++头文件互相包含导致的error: 'xxx' does not name a type问题
在一个源文件中,要声明或定义一个类的指针时,必须在使用前声明或定义该类,因此下面的代码会报错:class A{public: B *b;};class B{public: A *a;};int main(){ return 0;}报错为“error: ‘B’ does not name a type”,就是因为在A类中使用B *b之前没有声明或定义B类,如果在原创 2017-01-17 15:39:25 · 83363 阅读 · 2 评论 -
Qt中QMainWindow对象设置layout的方法
QMainWindow并没有setLayout()函数,因此不能使用setLayout()函数来设置layout,需要使用间接的方法。 需要做的只是先定义一个QWidget对象,然后使用QMainWindow::setCentralWidget()函数来将该QWidget对象设置为Central Widget,然后使用该QWidget对象的setLayout()函数,就可以了,不过后续对象都要原创 2017-01-12 23:27:30 · 8144 阅读 · 3 评论 -
QtEmbedded开发环境安装
首先下载源码包,解压后cd进去。首先安装QtEmbedded,./configure -embedded generic -qvfbmakesudo make install中间出错的话一般是有些依赖没装好,装好后重新编译安装。然后记得设置环境变量。 然后需要安装virtural framebuffer,用它来模拟一个嵌入式设备。在安装它之前,首先需要安装qt for x11,因为刚才下载的源码包原创 2016-10-20 15:35:05 · 2514 阅读 · 0 评论 -
libcurl的使用
简介libcurl是一个客户端URL传输库,支持很多协议(自行查看官方简介:https://curl.haxx.se/libcurl/),简而言之,这个库能爬网页,有了这个库,就不需要自己写socket来爬网页了,方便了很多。 此处使用的语言为C++,虽然libcurl有C++的binding,但是那样就得看两份文档了,太麻烦,况且官方文档提到了在C++下使用时,唯一需要注意的是回调函数不能为非静原创 2016-11-10 15:05:01 · 1501 阅读 · 0 评论 -
Qt中QTabWidget隐藏某些tab
对于一个QTabWidget,有时我们需要在不同的状态下显示不同的tab,需要隐藏掉某些tab。使用removeTab()固然可以做到,但是这样的话我们再次需要显示这些tab时再把它们加进去,有时候计算index会很麻烦。所以有没有什么办法可以在不删除tab的前提下隐藏掉某些tab呢,这样就能避免再次添加tab和计算index的麻烦。 遗憾的是Qt并没有对tab提供类似hide()或者setVis原创 2017-12-17 23:02:14 · 32257 阅读 · 12 评论 -
C++中将枚举量值映射到枚举量名的三种方法:使用Qt、手工映射与使用Better Enums
引子最近遇到这样一种场景:为了方便调试Qt程序,需要对某些Qt控件的主要事件(鼠标事件、键盘事件和焦点事件等)进行日志记录。Qt每种事件类都是QEvent类的派生类,其具体类型可使用QEvent::type()方法获得,该方法返回一个QEvent::Type类型的枚举量。所以最基本的实现是这样的(假设要对Widget类的事件进行记录,用标准输出代替日志输出):bool Widget::ev...原创 2018-04-14 19:59:23 · 4059 阅读 · 0 评论