Qt元对象系统 day5

Qt元对象系统 day5

内存管理

  • QObject以对象树的形式组织起来,当为一个对象创建子对象时,子对象回自动添加到父对象的children()列表中。父对象拥有子对象所有权,比如父对象可以在自己的析构函数中删除它的孩子对象。使用findChild()或findChildren()通过名字和类型查询孩子对象
QObject(QObject *parent = nullptr)
  • QObject及其派生类的对象,如果其parent非nullptr,那么其parent析构时会析构该对象。

  • 父子关系:父对象、子对象、父子关系。这是Qt中所特有的,与类的继承关系无关,传递参数是与parent有关(基类、派生类,或父类、子类,这是对于派生体系来说的,与parent无关)。

  • 在Qt中,最基础和核心的类是:QObject,QObject内部有一个名为children的QObjectList列表,会保存所有子对象,还有一个指针parent,用来指向父对象,当自己析构时,会先把自己从parent列表中删除并且析构所有的children。

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QRadioButton>//只有在debug模式下才显示调试窗口,如果在release模式下不显示调试窗口
#ifdef _DEBUG#pragma comment(linker,"/subsystem:console /entry:mainCRTStartup")
#else#pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")
#endif // _DEBUGint main(int argc, char* argv[])
{QApplication a(argc, argv);QWidget w;{QRadioButton* rBtn = new QRadioButton("男", &w);//设置对象名rBtn->setObjectName("man_rBtn");auto btn = new QPushButton("小瓜");//设置对象名btn->setObjectName("小瓜_大瓜");//如果指定了父对象,则不需要手动showbtn->setParent(&w);rBtn->move(100, 0);QObject::connect(btn, &QPushButton::clicked, [](){qDebug() << "小瓜";});//获取btn的父对象auto parentw = dynamic_cast<QWidget*>(btn->parent());//是否获取成功if (parentw){qDebug() << parentw;}//获取子对象列表const QObjectList& list = w.children();for (auto v : list){qDebug() << v;}//查找指定类型的子对象qDebug() << "sub object" << w.findChild<QPushButton*>();//查找指定的子对象名的子对象qDebug() << w.findChild<QWidget*>("小瓜_大瓜");}//把所有子对象添加到窗口之后再显示窗口w.show();return a.exec();
}
  • 运行结果
    在这里插入图片描述

释放内存

  • Qt里面有些还是得手动释放
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QRadioButton>//只有在debug模式下才显示调试窗口,如果在release模式下不显示调试窗口
#ifdef _DEBUG#pragma comment(linker,"/subsystem:console /entry:mainCRTStartup")
#else#pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")
#endif // _DEBUGint main(int argc, char* argv[])
{QApplication a(argc, argv);auto w = new QWidget;w->show();QObject::connect(w, &QObject::destroyed, []() {qDebug() << "释放成功";});int ret = a.exec();//1.直接使用delete释放(对于直接或间接继承QObject的类对象)delete w;//2.使用QOBject提供的安全释放的函数来释放对象(下一次运行到事情循环的时候,才去释放对象)//w->deleteLater(); //此处场景不能使用,因为事件循环已经结束了,当某个窗口不需要的时候就释放掉用这个return ret;
}
  • 运行结果
    在这里插入图片描述

Qt中的智能指针

  • 为了管理内存等资源,C++程序员通常采用RAII(Resource Acquisition Is Initialization)机制:在类的构造函数中申请资源,然后使用,最后在析构函数中释放资源。
  • 如果没有智能指针,程序员必须保证new对象能在正确的时机delete,四处编写异常捕获代码以释放资源,而智能指针则可以在退出作用域时(不管是正常流程离开或是因异常离开)总调用delete来析构在堆上动态分配的对象。
  • Qt中的智能指针:
智能指针描述
QPointer[QObject专享指针]QObject或子类对象释放时会自动指向nullptr
QScopedPointer[独享指针]超出作用域自动释放管理的对象
QSharedPointer[共享指针]
QWeakPointer[监视指针]
QScopedArrayPointer[独享数组指针]超出作用域自动释放管理的对象数组
QSharedDataPointer[隐式共享指针]读时共享,写时拷贝
QExplicitlySharedDataPointer[显示共享指针]读时共享,写时需要手动拷贝(通过detach()函数)

QPointer

  • 受保护指针QPointer的行为类似于普通c++指针T *,只是当被引用的对象被销毁时它会自动清除(不像普通c++指针,在这种情况下它会变成“悬浮指针”)。T必须是QObject的子类。
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QRadioButton>
#include <QPointer>
//只有在debug模式下才显示调试窗口,如果在release模式下不显示调试窗口
#ifdef _DEBUG#pragma comment(linker,"/subsystem:console /entry:mainCRTStartup")
#else#pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")
#endif // _DEBUGclass Text :public QWidget
{Q_OBJECT
public:Text(QWidget* parent = nullptr) :QWidget(parent){text_QPointer();}void text_QPointer(){//QPointer不会自动释放保存的对象QPointer btn = new QPushButton("小瓜", this);if (btn){qDebug() << "小瓜";}delete btn;//释放之后,btn会自动变为nullptrif (!btn){qDebug() << "小瓜不见了";}}
};int main(int argc, char* argv[])
{QApplication a(argc, argv);Text w;w.show();return a.exec();}#include "main.moc"
  • 运行结果
    在这里插入图片描述

QScopedPointer

  • 手动管理堆分配对象非常困难而且容易出错,通常的结果是代码泄漏内存并且难以维护。QScopedPointer是一个小型实用程序类,它通过将基于堆栈的内存所有权分配给堆分配(更通常称为资源获取初始化(RAII)),极大地简化了这一点。

  • QScopedPointer保证当当前作用域消失时,所指向的对象将被删除。

QSharedPointer

  • QSharedPointer是c++中的一个自动共享指针。它的行为和普通指针完全一样。

  • 如果没有其他QSharedPointer对象引用它,当它超出作用域时,QSharedPointer将删除它所持有的指针。

  • QSharedPointer对象可以从一个普通指针、另一个QSharedPointer对象或通过将QWeakPointer对象提升为强引用来创建。

QWeakPointer

  • 在c++中,QWeakPointer是对指针的自动弱引用。它不能用于直接解引用该指针,但可以用于验证该指针是否已在另一个上下文中被删除。

  • QWeakPointer对象只能通过从QSharedPointer赋值来创建。

QScopedArrayPointer

  • QScopedArrayPointer是一个QScopedPointer,默认使用delete[]操作符删除它所指向的对象。为了方便,它还提供了操作符[]

QSharedDataPointer

  • QSharedDataPointer类表示指向隐式共享对象的指针。

  • QSharedDataPointer使您可以轻松地编写自己的隐式共享类。QSharedDataPointer实现了线程安全的引用计数,确保将QSharedDataPointer添加到可重入类中不会使它们不可重入。

  • 许多Qt类都使用隐式共享,以将指针的速度和内存效率与类的易用性结合起来。有关更多信息,请参见共享类页面。

  • 假设您想让Employee类隐式共享。这个过程是:定义Employee类,使其拥有类型为QSharedDataPointer的单个数据成员。

  • 定义从QSharedData派生的EmployeeData类,以包含通常放入Employee类中的所有数据成员。

QExplicitlySharedDataPointer

  • QExplicitlySharedDataPointer类表示指向显式共享对象的指针。

  • QExplicitlySharedDataPointer使您可以轻松编写自己的显式共享类。QExplicitlySharedDataPointer实现了线程安全的引用计数,确保将QExplicitlySharedDataPointer添加到可重入类中不会使它们不可重入。

  • 除了一个很大的区别,QExplicitlySharedDataPointer就像QSharedDataPointer。最大的区别是,QExplicitlySharedDataPointer的成员函数在允许修改共享数据对象之前,不像QSharedDataPointer的非const成员那样在写操作(detach())时自动复制。有一个detach()函数可用,但如果您真的想要detach(),则必须自己调用它。这意味着QExplicitlySharedDataPointers的行为与常规的c++指针类似,只是通过进行引用计数并且在引用计数为0之前不删除共享数据对象,避免了悬浮指针的问题。

属性系统

  • Qt提供了一个复杂的属性系统,类似于一些编译器供应商提供的属性系统。然而,作为一个独立于编译器和平台的库,Qt不依赖于像__property或[property]这样的非标准编译器特性。Qt解决方案可以在Qt支持的每一个平台上使用任何标准的c++编译器。它基于元对象系统,也通过信号和插槽提供对象间通信。

  • 属性的行为类似于类数据成员,但它具有通过元对象系统访问的附加特性。

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QRadioButton>
#include <QPointer>
//只有在debug模式下才显示调试窗口,如果在release模式下不显示调试窗口
#ifdef _DEBUG#pragma comment(linker,"/subsystem:console /entry:mainCRTStartup")
#else#pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")
#endif // _DEBUGclass Person :public QObject
{Q_OBJECT
public:Person(){}
};int main(int argc, char* argv[])
{QApplication a(argc, argv);Person xiaogua;//1.通过方法设置一些成员变量xiaogua.setObjectName("小瓜");qDebug() << xiaogua.objectName();//2.通过属性来设置xiaogua.setProperty("objectName", "大瓜");qDebug() << xiaogua.objectName() << xiaogua.property("objectName");//3.如果设置类里面没有的属性,那么则会添加临时的属性xiaogua.setProperty("name", "小瓜");xiaogua.setProperty("age", 21);qDebug() << xiaogua.property("name") << xiaogua.property("age");return a.exec();}
#include "main.moc"
  • 运行结果
    在这里插入图片描述

声明自己的属性

  • 除了通过setProperty动态添加属性之外,怎样才能在代码中,声明属性呢?

  • 要声明属性,请在继承 QObject 的类中使用 Q_PROPERTY() 宏。

Q_PROPERTY(type name(READ getFunction [WRITE setFunction] |MEMBER memberName [(READ getFunction | WRITE setFunction)])[RESET resetFunction][NOTIFY notifySignal][REVISION int | REVISION(int[, int])][DESIGNABLE bool][SCRIPTABLE bool][STORED bool][USER bool][BINDABLE bindableProperty][CONSTANT][FINAL][REQUIRED])
  • 如果未指定 MEMBER 变量,则需要 READ 访问器函数。 它用于读取属性值。 理想情况下,const 函数用于此目的,它必须返回属性的类型或对该类型的 const 引用。 例如,QWidget::focus 是一个带有 READ 函数的只读属性,QWidget::hasFocus()。

  • WRITE 访问器函数是可选的。 它用于设置属性值。 它必须返回 void 并且必须只接受一个参数,该参数可以是属性的类型,也可以是指向该类型的指针或引用。 例如,QWidget::enabled 具有 WRITE 函数 QWidget::setEnabled()。 只读属性不需要 WRITE 函数。 例如,QWidget::focus 没有 WRITE 功能。

  • 如果未指定 READ 访问器函数,则需要 MEMBER 变量关联。 这使得给定的成员变量可读可写,而无需创建 READ 和 WRITE 访问器函数。 如果您需要控制变量访问,除了 MEMBER 变量关联之外,仍然可以使用 READ 或 WRITE 访问器函数。

  • RESET 功能是可选的。 它用于将属性设置回其特定于上下文的默认值。 例如,QWidget::cursor 有典型的 READ 和 WRITE 函数,QWidget::cursor() 和 QWidget::setCursor(),它还有一个 RESET 函数,QWidget::unsetCursor(),因为没有调用 QWidget:: setCursor() 可以表示重置为特定于上下文的光标。 RESET 函数必须返回 void 并且不带任何参数。

  • NOTIFY 信号是可选的。 如果已定义,则应指定该类中的一个现有信号,该信号在属性值更改时发出。 MEMBER 变量的 NOTIFY 信号必须采用零个或一个参数,该参数必须与属性的类型相同。 该参数将采用属性的新值。 NOTIFY 信号只应在属性真正被更改时发出,以避免在 QML 中不必要地重新评估绑定,例如。 当没有显式设置器的 MEMBER 属性需要时,Qt 会自动发出该信号。

  • REVISION 编号或 REVISION() 宏是可选的。 如果包含,它定义了要在 API 的特定修订版中使用的属性及其通知信号(通常用于暴露于 QML)。 如果不包含,则默认为 0。

  • DESIGNABLE 属性指示该属性是否应在 GUI 设计工具(例如 Qt Designer)的属性编辑器中可见。 大多数属性都是可设计的(默认为 true)。 有效值为真和假。

  • SCRIPTABLE 属性指示脚本引擎是否可以访问此属性(默认为 true)。 有效值为真和假。

  • STORED 属性指示该属性是否应该被认为是独立存在的,或者取决于其他值。 它还指示在存储对象的状态时是否必须保存属性值。 大多数属性是 STORED 的(默认为 true),但例如,QWidget::minimumWidth() 的 STORED 为 false,因为它的值只是从属性 QWidget::minimumSize() 的宽度分量中获取的,它是一个 QSize。

  • USER 属性指示该属性是被指定为该类的面向用户的属性还是用户可编辑的属性。 通常,每个类只有一个 USER 属性(默认为 false)。 例如,QAbstractButton::checked 是(可检查)按钮的用户可编辑属性。 请注意,QItemDelegate 获取和设置小部件的 USER 属性。

  • BINDABLE bindableProperty 属性表明该属性支持绑定,并且可以通过元对象系统 (QMetaProperty) 设置和检查与该属性的绑定。 bindableProperty 命名 QBindable 类型的类成员,其中 T 是属性类型。 这个属性是在 Qt 6.0 中引入的。

  • CONSTANT 属性的存在表明属性值是常量。 对于给定的对象实例,常量属性的 READ 方法在每次调用时都必须返回相同的值。 对于对象的不同实例,该常数值可能不同。 常量属性不能有 WRITE 方法或 NOTIFY 信号。

  • FINAL 属性的存在表明该属性不会被派生类覆盖。 这在某些情况下可用于性能优化,但并非由 moc 强制执行。 必须注意永远不要覆盖 FINAL 属性。

  • REQUIRED 属性的存在表明该属性应该由该类的用户设置。 这不是由 moc 强制执行的,并且对于暴露给 QML 的类最有用。 在 QML 中,除非设置了所有 REQUIRED 属性,否则无法实例化具有 REQUIRED 属性的类。

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QRadioButton>
#include <QPointer>
//只有在debug模式下才显示调试窗口,如果在release模式下不显示调试窗口
#ifdef _DEBUG#pragma comment(linker,"/subsystem:console /entry:mainCRTStartup")
#else#pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")
#endif // _DEBUG
int g_tel=666;
class Person :public QObject
{Q_OBJECT//让成员变量暴露给属性Q_PROPERTY(QString name MEMBER m_name NOTIFY nameChanged)Q_PROPERTY(int age MEMBER m_age NOTIFY ageChanged)//直接定义属性Q_PROPERTY(quint64 tel READ getTel WRITE setTel RESET resetTel NOTIFY telChanged)public:Person(){}//提供接口int age()const{ return m_age;}void setAge(int age) { m_age = age; }QString name() const { return m_name; }void setName(const QString& name) { m_name = name; }quint64 getTel()const { return g_tel; }void setTel(quint64 tel){if (g_tel != tel){g_tel = tel;emit telChanged(tel);}}void resetTel() { setTel(-1); }signals:void telChanged(quint64 tel);void ageChanged(int age);void nameChanged();protected:int m_age{};QString m_name{};
};int main(int argc, char* argv[])
{QApplication a(argc, argv);Person xiaogua;xiaogua.setName("小瓜");xiaogua.setAge(20);QObject::connect(&xiaogua, &Person::telChanged, [](quint64 tel){qDebug() << "tel changed" << tel;});QObject::connect(&xiaogua, &Person::ageChanged, [](){qDebug() << "age changed";});QObject::connect(&xiaogua, &Person::nameChanged, [](){qDebug() << "name changed";});//xiaogua.setTel(12345678);xiaogua.setProperty("tel", QVariant());xiaogua.setAge(21);xiaogua.setProperty("name", "ccc");qDebug() << xiaogua.property("name") << xiaogua.property("age") << xiaogua.property("tel");return a.exec();}
#include "main.moc"
  • 运行结果
    在这里插入图片描述

绑定属性

  • Qt提供了可绑定属性。可绑定属性是具有值或使用任何c++函数(通常是c++ lambda表达式)指定的属性。如果它们是使用c++函数指定的,那么当它们的依赖项发生变化时,它们就会自动更新。
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QRadioButton>
#include <QPointer>
#include<QProperty>
#include<QObjectBindableProperty>
//只有在debug模式下才显示调试窗口,如果在release模式下不显示调试窗口
#ifdef _DEBUG#pragma comment(linker,"/subsystem:console /entry:mainCRTStartup")
#else#pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")
#endif // _DEBUG//1,在Qobject子类中使用绑定属性
struct Circle : public QObject
{Q_OBJECT
public:Circle(){//添加绑定area.setBinding([=]{return M_PI * radius * radius;});}//QProperty<int> radius{};//QProperty<qreal> area{};signals:void radiusChanged();void areaCahnged();
public:Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(Circle, int, radius, 0, &Circle::radiusChanged);Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(Circle, qreal, area, 0, &Circle::areaCahnged);
};
//2,如果类没有继承自Qobject
struct Rect
{Rect(){area.setBinding([=]{return w * h;});}QProperty<int> w;QProperty<int> h;QProperty<int> area;
};int main(int argc, char* argv[])
{QApplication a(argc, argv);Circle c;QObject::connect(&c, &Circle::areaCahnged, []{qDebug() << "areaChange";});c.radius = 23;qDebug() << c.area;Rect r;r.w = 5;r.h = 9;qDebug() << r.area;return a.exec();
}#include "main.moc"

内省机制

  • 所谓内省是指面向对象语言的一种在运行期间查询对象信息的能力, 比如如果该语具有运行期间检查对象型别的能力,那么我们称它是型别内省(type intropection)的,型别内省可以用来实施多态。
  • Qt拓展了C++的内省机制,(实际上,它并没有采用C++的RTTI),而是提供了更为强大的元对象(meta object)机制,来实现内省。接下来,就让我们看看,Qt是如何扩展c++内省机制的。
  • 要深刻理解Qt的内省机制,首先理解QObjectQObject类是整个Qt对象模型的心脏,Qt对象模型最为核心的功能是提供一种无缝的对象通讯机制,即就是我们所熟知的信号和槽。QObject主要有三大职责: 内存管理、内省(intropection)与事件处理。本文将集中在在内省的讨论。以下代码介绍了QObject类提供的内省方法:
//判断该类是否继承自指定的类
bool inherits(const char *className) const;QWidget* w = new QWidget;
w.inherits("QObject");		//true
w.inherits("QWidget");		//false
  • 示例
#include<QApplication>
#include<QWidget>
#include<QMetaEnum>
class Test
{
public:Test(){QWidget w;qDebug() << w.inherits("QObject");auto metaObject =  w.metaObject();qDebug()<<metaObject->className();}
};//1,在命名空间中使用注册枚举
namespace Maye
{Q_NAMESPACEenum Type{Player,Enemy,Bullet};Q_ENUM_NS(Type)	//把枚举类型注册到元对象系统
}
//2,在类中注册枚举
struct Person : public QObject 
{Q_OBJECT
public:enum Identity{Student,Doctor,Teacher};Q_ENUM(Identity)
};
int main(int argc, char* argv[])
{QApplication a(argc, argv);Test t;using namespace Maye;Type type = Player;qDebug() << type;	//0  PlayerPerson::Identity id = Person::Doctor;qDebug() << id;//获取枚举信息QMetaEnum me = QMetaEnum::fromType<Person::Identity>();qDebug() << me.name() << me.keyCount();qDebug() << me.keyToValue("Teacher");qDebug() << me.valueToKey(Person::Doctor);return a.exec();
}
#include "main.moc"

QFlags

#include<QApplication>
#include<QFlags>
struct xiaogua : public QObject
{Q_OBJECT
public:enum AlignMent{Top = 1,Left = 1 << 2,Bottom = 1 << 3,Right = 1 << 4,Center = 1 << 5};Q_ENUMS(AlignMent)Q_DECLARE_FLAGS(AlignMentFlags, AlignMent)Q_FLAG(AlignMentFlags)
};int main(int argc, char* argv[])
{QApplication a(argc, argv);xiaogua::AlignMentFlags flags(xiaogua::Top | xiaogua::Left);if (flags.testFlag(xiaogua::Top)){qDebug() << "has top";}if (flags.testFlag(xiaogua::Left)){qDebug() << "has left";}return a.exec();
}
#include "main.moc"
  • 运行结果
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/154243.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于spso算法的航线规划

matlab2020a GitHub - duongpm/SPSO: Spherical Vector-based Particle Swarm Optimization

SpringBoot结合dev-tool 实现IDEA项目热部署

什么是热部署&#xff1f; 应用正在运行的时候升级功能, 不需要重新启动应用对于Java应用程序来说, 热部署就是在运行时更新Java类文件 通俗的来讲&#xff0c;应用在运行状态下&#xff0c;修改项目源码后&#xff0c;不用重启应用&#xff0c;会把编译的内容部署到服务器上…

超低延时直播技术演进之路-进化篇

一、概述 网络基础设施升级、音视频传输技术迭代、WebRTC 开源等因素&#xff0c;驱动音视频服务时延逐渐降低&#xff0c;使超低延时直播技术成为炙手可热的研究方向。实时音视频业务在消费互联网领域蓬勃发展&#xff0c;并逐渐向产业互联网领域加速渗透。经历了行业第一轮的…

```,```中间添加 # + 空格 + 空行后遇到的底部空行出错,书接上回,处理空行

【python查找替换&#xff1a;查找空行&#xff0c;空行前后添加&#xff0c;中间添加 # 空格 空行后遇到的第1行文字&#xff1f; - CSDN App】http://t.csdnimg.cn/QiKCV def is_blank(line):return len(line.strip()) 0txt 时间戳&#xff1a; ("%Y-%m-%d %H:%M:…

【排序算法】插入排序

文章目录 一&#xff1a;基本概念1.1 介绍1.2 原理1.3 插入排序法思想 二&#xff1a;代码实现2.1 源码2.2 执行结果2.3 测试八万条数据 三&#xff1a;算法分析3.1 时间复杂度3.2 空间复杂度3.3 稳定性 一&#xff1a;基本概念 1.1 介绍 插入式排序属于内部排序法&#xff0…

Xcode 15下,包含个推的项目运行时崩溃的处理办法

升级到Xcode15后&#xff0c;部分包含个推的项目在iOS17以下的系统版本运行时&#xff0c;会出现崩溃&#xff0c;由于崩溃在个推Framework内部&#xff0c;无法定位到具体代码&#xff0c;经过和个推官方沟通&#xff0c;确认问题是项目支持的最低版本问题。 需要将项目的最低…

K8S:K8S对外服务之Ingress

文章目录 一.Ingress基础介绍1.Ingress概念2.K8S对外暴露服务&#xff08;service&#xff09;主要方式&#xff08;1&#xff09;NodePort&#xff08;2&#xff09;LoadBalancer&#xff08;3&#xff09;externalIPs&#xff08;4&#xff09;Ingress 3.Ingress 组成&#x…

计算机网络 | OSI 参考模型

计算机网络 | OSI 参考模型 计算机网络 | OSI 参考模型应用层表示层会话层传输层网络层数据链路层物理层 参考视频&#xff1a;王道计算机考研 计算机网络 参考书&#xff1a;《2022年计算机网络考研复习指导》 计算机网络 | OSI 参考模型 OSI 参考模型自下而上分为7层&…

Redis 学习笔记

文章目录 一、基础命令1.1 通用命令1.2 String1.3 Hash1.4 List1.5 Set1.6 SortedSet 二、Redis 和数据库的数据一致性三、缓存穿透四、缓存雪崩五、缓存击穿 一、基础命令 1.1 通用命令 KEYS pattern 查找所有符合给定模式 pattern 的 key&#xff0c;其中 * 匹配零个或多个…

【Golang】gin框架入门

文章目录 gin框架入门认识gingo流行的web框架gin介绍快速入门 路由RESTful API规范请求方法URI处理函数分组路由 请求参数GET请求参数POST请求参数路径参数文件参数 响应字符串方式JSON方式XML方式文件格式设置HTTP响应头重定向YAML方式 模板渲染基本使用多个模板渲染自定义模板…

Qt中QTimer定时器的用法

Qt中提供了两种定时器的方式一种是使用Qt中的事件处理函数&#xff0c;另一种就是Qt中的定时器类QTimer。 使用QTimer类&#xff0c;需要创建一个QTimer类对象&#xff0c;然后调用其start()方法开启定时器&#xff0c;此后QTimer对象就会周期性的发出timeout()信号。 1.QTimer…

VMware centos7虚拟机修改静态IP

一、修改网络适配器 1、打开 2、使用管理员权限修改 3、按照图中步骤修改为 4、设置网关为10.0.0.2后保存即可 二、修改配置文件 1、输入下面代码进入修改&#xff08;网卡这里网卡名字为ens33&#xff0c;可使用ifcfig或ip a查看&#xff09; vi /etc/sysconfig/netwo…

使用vlc获取海康威视视频流

1.下载相关软件 1.1海康威视官网-服务支持-工具软件-设备网络搜索 下载地址&#xff1a; https://www.hikvision.com/cn/support/tools/hitools/注意&#xff1a;必须跟摄像头在同一个局域网下才可以使用设备网络搜索工具&#xff0c;才能使用vlc获取到视频流。 1.2下载VLC …

Hadoop----Azkaban的使用与一些报错问题的解决

1.因为官方只放出源码&#xff0c;并没有放出其tar包&#xff0c;所以需要我们自己编译&#xff0c;通过查阅资料我们可以使用gradlew对其进行编译&#xff0c;还是比较简单&#xff0c;然后将里面需要用到的服务文件夹进行拷贝&#xff0c;完善其文件夹结构&#xff0c;通常会…

leetcode 每日一题复盘(10.9~10.15)

leetcode 101 对称二叉树 这道题一开始想是用层序遍历,看每一层是否都对称,遇到一个问题就是空指针(子树为空)无法记录下来,同时会导致操作空指针的问题,因此需要修改入队条件,并用一个标志去表示空指针 vector<int>numv;for(int i0;i<size;i){TreeNode*frontque.fro…

SpringCloudGateway网关整合swagger3+Knife4j3,basePath丢失请求404问题

很多人都是照着别人的文章粘代码&#xff0c;我也是粘的&#xff0c;但是这样粘也会有问题&#xff0c;我搞这个Knife4j3的时候遇到两个问题&#xff0c;这里记录一下&#xff1a; 第一个是basePath丢失&#xff0c;第二个解决basePath丢失完又引发了会引起application/json数据…

React +ts + babel+webpack

babel babel/preset-typescript 专门处理ts "babel/cli": "^7.17.6", "babel/core": "^7.17.8", "babel/preset-env": "^7.16.11", "babel/preset-react": "^7.16.7", "babel/preset…

第4章 决策树

文章目录 4.1 基本流程4.2 划分选择4.2.1 信息增益4.2.2 增益率4.2.3 基尼指数 4.3 剪枝处理4.3.1 预剪枝4.3.2 后剪枝 4.4 连续与缺失值4.4.1 连续值处理4.4.2 缺失值处理 4.5 多变量决策树4.6 阅读材料 4.1 基本流程 决策树也称判定树&#xff0c;是一类常见的机器学习方法。…

35 WEB漏洞-逻辑越权之找回机制及接口安全

目录 找回重置机制接口调用乱用演示案例绑定手机验证码逻辑-Rep状态值篡改-实例某APP短信轰炸接口乱用-实例接口调用发包 文章分享&#xff1a;https://www.cnblogs.com/zhengna/p/15655691.html 有支付接口、短信发送接口&#xff0c;邮箱的发送接口等等&#xff0c;在接口这…

论文研读|Protecting Intellectual Property of Deep Neural Networks with Watermarking

目录 论文信息文章简介研究动机研究方法水印生成水印嵌入版权验证 实验结果有效性&#xff08;Effectiveness&#xff09;高效性&#xff08;Converge Speed&#xff09;保真度&#xff08;Functionality&#xff09;鲁棒性&#xff08;Robustness&#xff09;Anti-剪枝攻击&am…