持续更新中。。。
一、C++篇
设计模式
1. 单例
1.1 单例写法1
class Singleton {
public:
static Singleton& GetInstance() {
static Singleton instance;
return instance;
}
private:
Singleton() {}; // 私有化构造函数,防止外部创建实例
Singleton(const Singleton&); // 禁止拷贝构造函数
Singleton& operator=(const Singleton&); // 禁止赋值操作符重载
};
因为是static修饰过的,所以通过调用 Singleton::GetInstance()
可以获取到唯一实例的引用,并且保证了在整个程序中只有一个实例存在。
1.2 单例写法2
class Singleton:
{
// 其它成员
public:
static Singleton * GetInstance()
{
if (m_pInstance == NULL)
m_pInstance = new Singleton();
return m_pInstance;
}
private:
Singleton(){};
static Singleton * m_pInstance;
}
# 缺点:需要手动释放
1.3 单例模式3
class Singleton:
{
// 其它成员
public:
static Singleton * GetInstance(){...}
private:
Singleton(){};
static Singleton * m_pInstance;
class CGarbo // 它的唯一工作就是在析构函数中删除Singleton的实例
{
public:
~CGarbo(){
if (Singleton::m_pInstance)
delete Singleton::m_pInstance;
}
};
static CGarbo Garbo; // 定义一个静态成员,在程序结束时,系统会调用它的析构函数
}
会自动释放,但是不美观,还是第一种好。
但是无论哪种,在多线程的时候,都有问题,需要加锁。
2. 智能指针
2.1 make_shared创建智能指针
std::make_shared
是C++标准库中的一个模板函数,用于创建指定类型的shared_ptr
智能指针对象。它提供了一种便捷的方式来创建和管理动态分配的对象。
std::make_shared
函数的定义如下:
template<class T, class... Args>
shared_ptr<T> make_shared(Args&&... args);
使用std::make_shared
函数有以下优点:
- 更高的性能:
std::make_shared
一次性分配了内存空间来存储对象和引用计数,相比于先使用new
运算符创建对象再传递给shared_ptr
,可以减少一次内存分配,提高性能。 - 更安全的异常处理:如果在创建对象时抛出异常,
std::make_shared
会确保释放已分配的内存,避免内存泄漏。 - 简化的语法:
std::make_shared
可以通过自动推断对象类型,无需显式指定模板参数。
下面是一个使用std::make_shared
的示例:
#include <memory>
struct MyClass {
int value;
MyClass(int val) : value(val) {}
};
int main() {
auto ptr = std::make_shared<MyClass>(42);
// 使用ptr访问MyClass对象
return 0;
}
3. 等待一段时间
3.1 当前线程等待
#include <chrono>
#include <thread>
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
4. 线程相关
4.1 打印线程ID
#include <iostream>
#include <thread>
using namespace std;
cout << "子线程中显示子线程id为" << this_thread::get_id()<< endl;
4.2 C++线程写法
(随记)C++多线程的简单Demo_c++ 多线程demo-CSDN博客
二、QT篇
1. 全局信号类
头文件:globalSignal.h
#ifndef GLOBALSIGNAL_H
#define GLOBALSIGNAL_H
#include <QObject>
class GlobalSignal : public QObject
{
Q_OBJECT
public:
//获取单实例
static GlobalSignal* getInstance();
//释放单实例
static void deleteInstance();
signals:
void dataReceived(const QString& data);
void getValue(int value);
private:
//单实例对象指针
static GlobalSignal *globalSignal;
//构造、析构、拷贝构造、赋值构造私有
GlobalSignal(){};
~GlobalSignal(){};
GlobalSignal(const GlobalSignal &){};
const GlobalSignal &operator=(const GlobalSignal &){};
};
#endif // GLOBALSIGNAL_H
// 使用方式:
// 1. 引入头文件,在私有对象中添加 GlobalSignal *glbSignal;
//
// 2. 构造函数中创建:glbSignal = GlobalSignal::getInstance();
//
// 3. 触发方式:
// emit glbSignal->getValue(num);
// 4. 接收方式:
// connect(glbSignal,&GlobalSignal::getValue,this,[=](int value){
// QString msg = QString("接收到数据:nn:%1").arg(value);
// ui->textBrowser->append(msg);
// });
cpp文件:
#include "globalSignal.h"
//全局信号转发单例类: 饿汉式
GlobalSignal* GlobalSignal::globalSignal = new GlobalSignal();
GlobalSignal *GlobalSignal::getInstance()
{
return globalSignal;
}
void GlobalSignal::deleteInstance()
{
if(globalSignal)
{
delete globalSignal;
globalSignal = nullptr;
}
}
2. 几种多线程方式
详细链接:QT中,QT线程四种写法的对比和写法示例-CSDN博客
2.1 moveToThread
- 自己写一个继承自QObject的类调用方式:这个是测试的,很多都可以删掉
#include <QObject>
#include <QDebug>
#include <QThread>
class MyWorker : public QObject
{
Q_OBJECT
public:
explicit MyWorker(QObject *parent = nullptr);
~MyWorker();
private:
void func(const QString& cmd);
public slots:
void doSomething(const QString& cmd);
void doThis();
signals:
void resultNotify(const QString& des); // 结束信号
private:
bool flag = true;
int num = 10;
};
// ***************************************
MyWorker::MyWorker(QObject *parent) : QObject(parent)
{
qDebug() << "Worker()" << "thread:" << QThread::currentThreadId();
}
MyWorker::~MyWorker()
{
qDebug() << "~Worker()" << "thread:" << QThread::currentThreadId();
}
void MyWorker::func(const QString &cmd = "test")
{
qDebug() << "func()" << "thread:" << QThread::currentThreadId();
while (num--) {
qDebug()<<"func:"<<cmd;
QThread::sleep(1);
}
emit resultNotify(cmd);
}
void MyWorker::doSomething(const QString &cmd)
{
qDebug() << "doSomething()" << "thread:" << QThread::currentThreadId();
flag = true;
func(cmd);
}
void MyWorker::doThis()
{
qDebug() << "doThis()" << "thread:" << QThread::currentThreadId();
int n=10;
while (n--) {
qDebug()<<"doThis:";
QThread::sleep(1);
}
}
- 调用方式1:必须使用信号触发
# 这个写在头文件:
QThread myWorkThread;
MyWorker myWorker;
# 这个写构造函数里面
myWorker.moveToThread(&myWorkThread);
myWorkThread.start();
# 调用方式:------------------------------------------------
// 方式一:直接调用,还是主线程,千万别这么用!!!
// myWorker.doSomething("test");
// 方式二:信号关联
// 带参数:
connect(this,&MainWindow::doSomething,&myWorker,&MyWorker::doSomething);
emit doSomething("test");
// 不带参数:
connect(this,&MainWindow::doThis,&myWorker,&MyWorker::doThis);
emit doThis();
- 调用方式2:像使用普通函数一样
myThread = new QThread();
myworker = new Worker();
myworker->moveToThread(myThread);
myThread->start();
//myworker.init(); // 还是主线程,别用
// 一般的调用方法:
connect(this,&MainWindow::doInit,myworker,&Worker::init);
emit doInit();
// 简化写法:
QMetaObject::invokeMethod(myworker,"init");
2.2 QtConcurrent快速开启线程
有的版本可能需要在pro中,添加 QT += concurrent ,未测试。我发现我不加也能用。
调用方式:
1. QFuture<void> future = QtConcurrent::run(&worker, &Worker::doWork);
2. QtConcurrent::run([=](){ worker->UDPtest("直接调用即可"); });
或者:
QtConcurrent::run([=](){
worker->UDPtest("UDP test");
});
3. run很多写法,用法不固定,我喜欢方法2,其他写法可自行百度。
注意:
如果想在单独开启的线程中共享主函数的资源,要么使用 = ,然后传递指针,要么就是使用引用 & ,否则无法进入匿名表达式。
2.3 继承自QThread
只有run()函数里面,才是多线程,不推荐使用。还不如使用QtConcurrent::run()呢。
2.4 QRunnable
继承自QRunnable,然后使用下面这个启动:
Worker *work_0 = new Worker();
QThreadPool::globalInstance()->start(work_0);
简单易用,不过显然没有前面两种方便。
11. Windows的QT项目打包
+ release 模式,编译运行一次,然后把exe文件复制到其他目录下。
+ 根据自己的版本和编译模式搜索:官方自带的命令行工具(普通的CMD不行)
+ 使用QT自带的cmd,管理员 如 Qt 5.14.2 (MinGW 7.3.0 64-bit)
+ 然后 : e: 进入到E盘
+ cd 路径 cd E:\QT_project\MyLovers1\result\
+ 执行: windeployqt XX.exe
+ 然后把其他第三方库放进来,最后测试一下。
+ 如果需要,可以使用Enigma Virtual Box将整个文件打包为一个EXE程序。
12. 延时执行:
QThread::sleep() 和 Sleep() 可能导致主线程和其他线程的阻塞,造成卡顿
推荐延时使用:
QTimer::singleShot(2000, [=](){
qDebug() << "Delayed execution after 2 seconds";
});
如果是子线程,不怕卡顿的话,可以使用QThread::sleep()
如果时间比较长,可能造成卡顿,可以使用这种方法:
// 创建一个事件循环对象
QEventLoop eventLoop;
QTimer::singleShot(2000, [&eventLoop](){
qDebug() << "Delayed execution after 2 seconds";
eventLoop.quit(); // 退出事件循环
});
// 进入事件循环并等待定时器触发
eventLoop.exec();
13. MSVC解决中文乱码
在pro文件中添加:
msvc {
QMAKE_CFLAGS += /utf-8
QMAKE_CXXFLAGS += /utf-8
}
14. 解决打开子窗口任务栏图标隐藏
但是为了防止关闭子窗口的时候,并没有合理的释放资源,先提前定义指针,只有点击按钮,才创建对象,关闭的时候,记得判断是否创建过:
void MainWindow::on_mainBtn_1_clicked()
{
if(setting_win == nullptr){
setting_win = new SettingUI(this);
connect(setting_win,&SettingUI::closed,[=](){
this->show();
});
}
this->hide();
setting_win->show();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
event->accept();
if(exper_win!=nullptr){delete exper_win;exper_win->stopAllDev();}
if(data_win!=nullptr)delete data_win;
if(setting_win!=nullptr)delete setting_win;
deleteLater();
}
15. linedit限制范围
#include <QIntValidator>
#include <QDoubleValidator>
#include <QIntValidator>
1.只允许输入整型
ui->lineEdit->setValidator(new QIntValidator(ui->lineEdit));
2.只允许输入数字
ui->lineEdit->setValidator(new QRegExpValidator(QRegExp("[0-9]+$")));
2.1.只允许数字0-9且长度为11位
ui->lineEdit->setValidator(new QRegExpValidator(QRegExp("[0-9]{11}")));
3.只能输入字母和数字
ui->lineEdit->setValidator(new QRegExpValidator(QRegExp("[a-zA-Z0-9]+$")));
4.只能输入大写字母
ui->lineEdit->setValidator(new QRegExpValidator(QRegExp("^[A-Z]+$")));
5.只能输入小写字母
ui->lineEdit->setValidator(new QRegExpValidator(QRegExp("^[a-z]+$")));
6.只能输入字母
ui->lineEdit->setValidator(new QRegExpValidator(QRegExp("^[A-Za-z]+$")));
7.输入浮点型数据
非负浮点数(正浮点数 + 0):"^\d+(\.\d+)?$"
正浮点数:"^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$"
非正浮点数(负浮点数 + 0):"^((-\d+(\.\d+)?)|(0+(\.0+)?))$"
负浮点数:"^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$"
浮点数:"^(-?\d+)(\.\d+)?$"
8.输入-255~255的整数
ui->lineEdit->setValidator(new QRegExpValidator(QRegExp("^-?(255|[1,2]?[0-4]?\\d|[1,2]?5[0-4]?)$")));
9.限制浮点数输入范围为[-90,90]并限定为小数位后4位
ui->lineEdit->setValidator(new QRegExpValidator(QRegExp rx("^-?(90|[1-8]?\\d(\\.\\d{1,4})?)$")));
10.输入格式 (年-月-日)
ui->lineEdit->setValidator(new QRegExpValidator(QRegExp("^(d{2}|d{4})-((0([1-9]{1}))|(1[1|2]))-(([0-2]([1-9]{1}))|(3[0|1]))$")));
10.1.输入格式(月/日/年)
ui->lineEdit->setValidator(new QRegExpValidator(QRegExp("^((0([1-9]{1}))|(1[1|2]))/(([0-2]([1-9]{1}))|(3[0|1]))/(d{2}|d{4})$")));
11.只能中文输入
ui->lineEdit->setValidator(new QRegExpValidator(QRegExp("[\u4e00-\u9fa5]+$")));
// 限制范围:****************************************************************
ui->lineEdit_acqTime->setValidator(new QIntValidator(20, 2000,ui->lineEdit_acqTime));
ui->lineEdit_lineSwapTime->setValidator(new QDoubleValidator(0.03, 0.1,2,ui->lineEdit_lineSwapTime));
16. QT的pro:
# 新加入模块
QT += core gui multimediawidgets
# 执行文件编译到 /bin目录中
DESTDIR = $$PWD/bin
# 添加子模块,以MainCtlModule为例,需要新建MainCtlModule文件夹,以及内部的MainCtlModule.pri文件
INCLUDEPATH += $$PWD/MainCtlModule
include($$PWD/MainCtlModule/MainCtlModule.pri)
# 获取系统架构信息,根据系统指定环境
system_arch = $$system(uname -m)
equals(system_arch, "x86_64") {
message("x86_64 架构")
# 虚拟机环境:************************
CONFIG += link_pkgconfig
PKGCONFIG += gstreamer-1.0 gstreamer-plugins-base-1.0 #gtk+-3.0
LIBS += -lX11
LIBS +=-lglib-2.0
LIBS +=-lgobject-2.0
LIBS +=-lgstreamer-1.0 # <gst/gst.h>
LIBS +=-lgstvideo-1.0 # <gst/video/videooverlay.h>
LIBS +=-L/usr/lib/x86_64-linux-gnu/gstreamer-1.0
#LIBS +=-lgstautodetect
LIBS +=-lgstaudio-1.0
LIBS +=-lgstapp-1.0
LIBS += -L/usr/local/lib/ -lgstrtspserver-1.0
INCLUDEPATH += \
/usr/include/glib-2.0 \
/usr/lib/x86_64-linux-gnu/glib-2.0/include \
/usr/include/gstreamer-1.0 \
/usr/lib/x86_64-linux-gnu/gstreamer-1.0/include
}else:equals(system_arch, "aarch64") {
message("aarch64 架构")
}else {
error("不支持的架构: $$system_arch")
}
三、其他
1. Windows好用工具记录:
- utools 非常方便的插件合集
- pixpin 新晋截图神器
- cmder 好用的命令行工具,可以在Windows电脑,像Linux那些命令来操作
- Snipaste 之前的截图神器
- Win + Shift + S 自由截图
- Everything 文件搜索神器
- notePad++ 好用的TXT编辑器
- MobaXterm 联调神器,可以链接串口、SSH、FTP、VNC。。。很多设备
- Bandicam 好用的录屏软件
- typora 请下载旧版,makedown神器
- GifCam 好用的GIF动图截图工具
- iperf 测带宽和网速
- Navicat 多种数据库连接
- VLC 超好用的视频播放和音视频开发播放器
- OBS 免费的录屏和直播软件
- sscom 超好用的串口和网络调试工具
- Enigma Virtual Box 封装工具
- 向日葵 远程桌面
- 亿图 好用的画图工具,各种工程图和导图等等,还有丰富的素材
- Iris_Pro 护眼软件
- vspd 虚拟串口工具
- HEU_KMS_Activator window和office激活
- npcap 扫描工具,网安和黑客常用
- Wireshark 抓包工具
- VMware 虚拟机
- 网易有道翻译 截图翻译
- 小熊猫dev 学习C++入门的IDE神器,适合学生
- drow.io 免费好用的绘图软件,平替vioso
- 躺平设计家 装修设计软件,3D,免费
2. Linux好用工具记录
- FileZilla Linux中文件传输
- iftop 查看网卡、IP、端口的流量
- tcpdump 类似libpcap,可以查看指定IP和端口流量,可以抓包保存文件
- gitg 图形化git工具
- Goolge Chrome 谷歌浏览器
- Onboard 虚拟键盘
- ffmpeg 音视频框架和工具
- gstreamer 音视频框架和工具
- wireshark 抓包神器
- VLC 播放器神器
- Vim 编辑神器
- Typora markdown神器,不过要下载旧版
- iperf3 生成网络数据,可用于测试网速
- v4l-utils 查看相机参数的工具
- v4l2loopback-utils 虚拟相机
- iproute2 和 net-tools 网络工具
- linux-image-() 通过uname -r查看,安装某个版本的内核
- docker 容器
- remmina-common 远程桌面,支持VNC
- qt
- anaconda 好用的python环境,比如jupyter notebook
- nginx-extras nginx服务器
- expect expect脚本
3. C++开发框架或者库
- ffmpeg 音视频开发框架1
- gstreamer 音视频开发框架2
- NGINX web常用的工具
- OpenGL 渲染
- OpenCV 图片和视频处理,还有AI识别
- libssh ssh
- libpcap 抓包
待补充...