Qt快速学习(一)--对象,信号和槽

news2024/11/24 5:43:43

目录

1.Qt概述

1.1 什么是Qt

2.2 手动创建

2.3 pro文件

2.4 一个最简单的Qt应用程序

       3 第一个Qt小程序

3.1 按钮的创建

3.2 对象模型(对象树)

      3.3 Qt窗口坐标体系

4 信号和槽机制

        4.1 系统自带的信号和槽

4.2 自定义信号和槽

    4.3信号槽的拓展

        4.4 Qt4版本的信号槽写法

        4.5 Lambda表达式 

1.Qt概述

      

1.1 什么是Qt

Qt是一个Qt是一个跨平台的C++图形用户界面应用程序框架。它为应用程序开发者提供建立艺术级图形界面所需的所有功能。它是完全面向对象的,很容易扩展,并且允许真正的组件编程

系统会默认给我们添加main.cpp、mywidget.cpp、 mywidget.h和一个.pro项目文件,点击完成,即可创建出一个Qt桌面程序。

2.2 手动创建

        添加一个空项目

        

 选择【choose】进行下一步。设置项目名称和路径 —> 选择编译套件 --> 修改类信息 --> 完成(步骤同上),生成一个空项目。在空项目中添加文件:在项目名称上单击鼠标右键弹出右键菜单,选择【添加新文件】

        

 弹出新建文件对话框

        

 在此对话框中选择要添加的类或者文件,根据向导完成文件的添加。   

2.3 pro文件

        在使用Qt向导生成的应用程序.pro文件格式如下:

        

QT       += core gui  //包含的模块

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets //大于Qt4版本 才包含widget模块

TARGET = QtFirst  //应用程序名  生成的.exe程序名称

TEMPLATE = app    //模板类型    应用程序模板

SOURCES += main.cpp\   //源文件

        mywidget.cpp

HEADERS  += mywidget.h   //头文件

.pro就是工程文件(project),它是qmake自动生成的用于生产makefile的配置文件。.pro文件的写法如下:

  1. 注释从“#”开始,到这一行结束。

模板变量告诉qmake为这个应用程序生成哪种makefile。下面是可供使用的选择:TEMPLATE = app。

       2.app-建立一个应用程序的makefile。这是默认值,所以如果模板没有被指定,这个将被使用

      3. lib - 建立一个库的makefile

      4. vcapp - 建立一个应用程序的VisualStudio项目文件。

      5.vclib - 建立一个库的Visual Studio项目文件

 subdirs -这是一个特殊的模板,它可以创建一个能够进入特定目录并且为一个项目文件生成makefile并且为它调用make的makefile。

#指定生成的应用程序名:

        TARGET = QtDemo

#工程中包含的头文件

        HEADERS += include/painter.h

#工程中包含的.ui设计文件

        FORMS += forms/painter.ui

#工程中包含的源文件

        SOURCES += sources/main.cpp sources

#工程中包含的资源文件

        RESOURCES += qrc/painter.qrc

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

这条语句的含义是,如果QT_MAJOR_VERSION大于4(也就是当前使用的Qt5更高版本)需要增加widgets模块。如果项目仅需支持Qt5也可以直接添加“QT += widgets”一句。不过为了保持代码兼容,最好还是按照QtCreator生成的语句编写

4#配置信息

CONFIG用来告诉qmake关于应用程序的配置信息。CONFIG += c++11 //使用c++11的特性。在这里使用“+=”,是因为我们添加我们的配置选项到任何一个已经存在中。这样做比使用“=”那样替换已经指定的所有选项更安全。

2.4 一个最简单的Qt应用程序

        main入口函数中

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

解释:

  1. Qt系统提供的标准类名声明头文件没有.h后缀
  2. Qt一个类对应一个头文件,类名就是头文件名
  3. QApplication应用程序类

               3.1 管理图形用户界面应用程序的控制流和主要设置

               3.2是Qt的整个后台管理的命脉它包含主事件循环,在其中来自窗口系统和其它资源的所有事件处理和调度。它也处理应用程序的初始化和结束,并且提供对话管理.

                3.3 对于任何一个使用Qt的图形用户界面应用程序,都正好存在一个QApplication 对象,而不论这个应用程序在同一时间内是不是有0、1、2或更多个窗口。

  1. a.exec()

程序进入消息循环,等待对用户输入进行响应。这里main()把控制权转交给Qt,Qt完成事件处理工作,当应用程序退出的时候exec()的值就会返回。在exec()中,Qt接受并处理用户和系统的事件并且把它们传递给适当的窗口部件。

       3 第一个Qt小程序

3.1 按钮的创建

        在Qt程序中,最常用的控件之一就是按钮了,首先我们来看下如何创建一个按钮

mywidget.cpp 

#include "mywidget.h"
#include<QPushButton>
#include"mypushbutton.h"
#include<QtDebug>
MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{

    QPushButton *btn=new QPushButton();

//    btn->show(); //show 使用顶层的方式弹出。

    //如果想显示到当前的窗口中,需要做依赖
    btn->setParent(this);
    btn->setText("德玛西亚");

    //按钮2
    QPushButton *btn2=new QPushButton("第二个",this);

    //移动btn2
    btn2->move(100,100);

    //如何重置窗口的大小。按钮同样可以重置大小。
//    resize(1600,1400);
//    btn->resize(40,80);

    //指定窗口的标题
    setWindowTitle("第一个窗口");

    //设置窗口固定的大小。
    setFixedSize(1000,800);


    MyPushButton *mybtn=new MyPushButton();
    mybtn->setParent(this);
    mybtn->setText("this is my button");
    mybtn ->move(200,200);
    //connect(信号发送者,发送信号,信号的接受这,处理槽函数)有点松散耦合的作用

    connect(mybtn,&QPushButton::clicked,this,&QWidget::close);



}

MyWidget::~MyWidget()
{
    qDebug()<<"Mywidget()'s destrction";
}

       mywidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    MyWidget(QWidget *parent = 0);
    ~MyWidget();
};

#endif // MYWIDGET_H

main.cpp

#include "mywidget.h"
#include <QApplication> //Qapplication 应用程序类的头文件。



//程序的入口, int argc 命令行数量,命令行变量的数组。
int main(int argc, char *argv[])
{

    //应用程序对象有且仅有一个。
    QApplication a(argc, argv);

    //通过--窗口类,实例化对象。
    MyWidget w;

    //窗口是不会默认弹出的,需要使用show进行显示。
    w.show();

    //进入一个消息循环的机制。  阻塞的功能。
    return a.exec();
}

上面代码中,一个按钮其实就是一个QPushButton类下的对象,如果只是创建出对象,是无法显示到窗口中的,所以我们需要依赖一个父窗口,也就是指定一个父亲利用setParent函数即可,如果想设置按钮上显示的文字利用setText,移动按钮位置用move对于窗口而言,我们可以修改左上角窗口的标题setWindowTitle,重新指定窗口大小:resize,或者设置固定的窗口大小setFixedSize。

3.2 对象模型(对象树)

        在Qt中创建对象的时候会提供一个Parent对象指针,下面来解释这个parent到底是干什么的

QObject是以对象树的形式组织起来的。

1.当你创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是 parent,也就是父对象指针。这相当于,在创建QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表。

2.当父对象析构的时候,这个列表中的所有对象也会被析构。(注意,这里的父对象并不是继承意义上的父类!)这种机制在 GUI 程序设计中相当有用。例如,一个按钮有一个QShortcut(快捷键)对象作为其子对象。当我们删除按钮的时候,这个快捷键理应被删除。这是合理的。

3.QWidget是能够在屏幕上显示的一切组件的父类

        QWidget继承自QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件。因此,它会显示在父组件的坐标系统中,被父组件的边界剪裁。例如,当用户关闭一个对话框的时候,应用程序将其删除,那么,我们希望属于这个对话框的按钮、图标等应该一起被删除。事实就是如此,因为这些都是对话框的子组件。

4.当然,我们也可以自己删除子对象,它们会自动从其父对象列表中删除。比如,当我们删除了一个工具栏时,其所在的主窗口会自动将该工具栏从其子对象列表中删除,并且自动调整屏幕显示

Qt 引入对象树的概念,在一定程度上解决了内存问题。

       当一个QObject对象在堆上创建的时候,Qt 会同时为其创建一个对象树。不过,对象树中对象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。

      任何对象树中的 QObject对象 delete 的时候,如果这个对象有 parent,则自动将其从 parent 的children()列表中删除;如果有孩子,则自动 delete 每一个孩子。Qt 保证没有QObject会被 delete 两次,这是由析构顺序决定的。

如果QObject在栈上创建,Qt 保持同样的行为。正常情况下,这也不会发生什么问题。来看下下面的代码片段。

{
    QWidget window;
    QPushButton quit("Quit", &window);
}

作为父组件的 window 和作为子组件的 quit 都是QObject的子类(事实上,它们都是QWidget的子类,而QWidget是QObject的子类)。这段代码是正确的,quit 的析构函数不会被调用两次,因为标准 C++要求,局部对象的析构顺序应该按照其创建顺序的相反过程。因此,这段代码在超出作用域时,会先调用 quit 的析构函数,将其从父对象 window 的子对象列表中删除,然后才会再调用 window 的析构函数。

但是,如果我们使用下面的代码:

{
    QPushButton quit("Quit");
    QWidget window;
    quit.setParent(&window);
}

    情况又有所不同,析构顺序就有了问题。我们看到,在上面的代码中,作为父对象的 window 会首先被析构,因为它是最后一个创建的对象。在析构过程中,它会调用子对象列表中每一个对象的析构函数,也就是说, quit 此时就被析构了。然后,代码继续执行,在 window 析构之后,quit 也会被析构,因为 quit 也是一个局部变量,在超出作用域的时候当然也需要析构。但是,这时候已经是第二次调用 quit 的析构函数了,C++ 不允许调用两次析构函数,因此,程序崩溃了。由此我们看到,Qt 的对象树机制虽然帮助我们在一定程度上解决了内存问题,但是也引入了一些值得注意的事情。这些细节在今后的开发过程中很可能时不时跳出来烦扰一下,所以,我们最好从开始就养成良好习惯,在 Qt 中,尽量在构造的时候就指定 parent 对象,并且大胆在堆上创建。

      3.3 Qt窗口坐标体系

        

坐标体系:以左上角为原点(0,0),X向右增加,Y向下增加。

对于嵌套窗口,其坐标是相对于父窗口来说的。

4 信号和槽机制

        信号槽是 Qt 框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。

        4.1 系统自带的信号和槽

下面我们完成一个小功能,上面我们已经学习了按钮的创建,但是还没有体现出按钮的功能,按钮最大的功能也就是点击后触发一些事情,比如我们点击按钮,就把当前的窗口给关闭掉,那么在Qt中,这样的功能如何实现呢?其实无法两行代码就可以搞定了,我们看下面的代码。

QPushButton * quitBtn = new QPushButton("关闭窗口",this);
  connect(quitBtn,&QPushButton::clicked,this,&MyWidget::close);

第一行是创建一个关闭按钮,这个之前已经学过,第二行就是核心了,也就是信号槽的使用方式。

connect()函数最常用的一般形式:

        connect(sender, signal, receiver, slot);

      参数解释:

        sender:发出信号的对象

        signal:发送对象发出的信号

        receiver:接收信号的对象

        slot:接收对象在接收到信号之后所需要调用的函数(槽函数)

那么系统自带的信号和槽通常如何查找呢,这个就需要利用帮助文档了,在帮助文档中比如我们上面的按钮的点击信号,在帮助文档中输入QPushButton,首先我们可以在Contents中寻找关键字 signals,信号的意思,但是我们发现并没有找到,这时候我们应该想到也许这个信号的被父类继承下来的,因此我们去他的父类QAbstractButton中就可以找到该关键字,点击signals索引到系统自带的信号有如下几个。

这里的clicked就是我们要找到,槽函数的寻找方式和信号一样,只不过他的关键字是slot。

4.2 自定义信号和槽

        使用connect()可以让我们连接系统提供的信号和槽。但是,Qt 的信号槽机制并不仅仅是使用系统提供的那部分,还会允许我们自己设计自己的信号和槽。 下面我们看看使用 Qt 的信号槽:

        首先定义一个学生类和老师类:老师类中声明信号 饿了 hungry,signals:

teacher.h

#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>

class Teacher : public QObject
{
    Q_OBJECT
public:
    explicit Teacher(QObject *parent = 0);

//自定义的信号需要写到sinal 中,返回值是void,只需要声明,不需要实现,可以有参数,可以发生重载的。

signals:
        void hungry();
        void hungry(QString foodName);

public slots:
};

#endif // TEACHER_H

 teacher.cpp

#include "teacher.h"

Teacher::Teacher(QObject *parent) : QObject(parent)
{

}

student.h 

#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

class Student : public QObject
{
    Q_OBJECT
public:
    //禁止隐式类型转换的功能,explicit
    explicit Student(QObject *parent = 0);

signals:

public slots:
    //自定义槽函数的地方 Q.0 5 可以写成全局,可以写在public 作用或者lambda 表达式

    void treat();
    void treat(QString foodName);




};

#endif // STUDENT_H

    student.cpp

#include "student.h"
#include<QDebug>
Student::Student(QObject *parent) : QObject(parent)
{

}



 void Student:: treat(){


     qDebug()<<"请老师吃饭";

 }

 void Student:: treat(QString foodName){

     //将QString 转成char* footName.toUft8().data();



     qDebug()<<"请老师吃饭,老师要吃: "<<foodName.toUtf8().data();
 }

自定义信号槽需要注意的事项

  1. 发送者和接收者都需要是QObject的子类(当然,槽函数是全局函数、Lambda 表达式等无需接收者的时候除外);
  2. 信号和槽函数返回值是 void
  3. 信号只需要声明,不需要实现
  4. 槽函数需要声明也需要实现
  5. 槽函数是普通的成员函数,作为成员函数,会受到 public、private、protected 的影响;
  6. 使用 emit 在恰当的位置发送信号;
  7. 使用connect()函数连接信号和槽。
  8. 任何成员函数、static 函数、全局函数和 Lambda 表达式都可以作为槽函数
  9. 信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。

如果信号和槽的参数不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少)。

    4.3信号槽的拓展

        1.一个信号可以和多个槽相连

        如果是这种情况,这些槽会一个接一个的被调用,但是它们的调用顺序是不确定的

        2.多个信号可以连接到一个槽

      只要任意一个信号发出,这个槽就会被调用

        3. 一个信号可以连接到另外的一个信号

        当第一个信号发出时,第二个信号被发出。除此之外,这种信号-信号的形式和信号-槽的形式没有什么区别

        4.槽可以被取消链接。

        这种情况并不经常出现,因为当一个对象delete之后,Qt自动取消所有连接到这个对象上面的槽。

        

        5.信号槽可以断开

利用disconnect关键字是可以断开信号槽的

  1. 使用Lambda 表达式

在使用 Qt 5 的时候,能够支持 Qt 5 的编译器都是支持 Lambda 表达式的。

在连接信号和槽的时候,槽函数可以使用Lambda表达式的方式进行处理。后面我们会详细介绍什么是Lambda表达式。

        4.4 Qt4版本的信号槽写法

        

connect(zt,SIGNAL(hungry(QString)),st,SLOT(treat(QString)));

        这里使用了SIGNAL和SLOT这两个宏,将两个函数名转换成了字符串。注意到connect()函数的 signal 和 slot 都是接受字符串,一旦出现连接不成功的情况,Qt4是没有编译错误的(因为一切都是字符串,编译期是不检查字符串是否匹配),而是在运行时给出错误。这无疑会增加程序的不稳定性。Qt5在语法上完全兼容Qt4,而反之是不可以的。

        4.5 Lambda表达式 

        C++11中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作。首先看一下Lambda表达式的基本构成:

        

[capture](parameters) mutable ->return-type

{

        statement

}

[函数对象参数](操作符重载函数参数)mutable ->返回值{函数体}

         

① 函数对象参数;

[],标识一个Lambda的开始,这部分必须存在,不能省略。函数对象参数是传递给编译器自动生成的函数对象类的构造函数的。函数对象参数只能使用那些到定义Lambda为止时Lambda所在作用范围内可见的局部变量(包括Lambda所在类的this)。函数对象参数有以下形式:

1.空。没有使用任何函数对象参数。

2.=。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。

3.&。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是引用传递方式(相当于编译器自动为我们按引用传递了所有局部变量)

4.this。函数体内可以使用Lambda所在类中的成员变量

5.a。将a按值进行传递。按值进行传递时,函数体内不能修改传递进来的a的拷贝,因为默认情况下函数是const的。要修改传递进来的a的拷贝,可以添加mutable修饰符。

6.&a。将a按引用进行传递、

7.a, &b。将a按值进行传递,b按引用进行传递

8.=,&a, &b。除a和b按引用进行传递外,其他参数都按值进行传递

9.&, a, b。除a和b按值进行传递外,其他参数都按引用进行传递

② 操作符重载函数参数;

标识重载的()操作符的参数,没有参数时,这部分可以省略。参数可以通过按值(如:(a,b))和按引用(如:(&a,&b))两种方式进行传递.

可修改标示符;

mutable声明,这部分可以省略。按值传递函数对象参数时,加上mutable修饰符后,可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身。

QPushButton * myBtn = new QPushButton (this);
    QPushButton * myBtn2 = new QPushButton (this);
    myBtn2->move(100,100);
    int m = 10;

    connect(myBtn,&QPushButton::clicked,this,[m] ()mutable { m = 20; qDebug() << m; });

    connect(myBtn2,&QPushButton::clicked,this,[=] ()  { qDebug() << m; });

    qDebug() << m;

④ 函数返回值;

->返回值类型,标识函数返回值的类型,当返回值为void,或者函数体中只有一处return的地方(此时编译器可以自动推断出返回值类型)时,这部分可以省略。

⑤ 是函数体;

{},标识函数的实现,这部分不能省略,但函数体可以为空。

总体介绍

  1. Qt简介
    1. 发展史
      1. 1991 奇趣科技
    2. 版本
      1. 商业版
      2. 开源版
    3. 优点
      1. 跨平台
      2. 接口简单 容易上手
      3. 一定程度上简化了内存回收机制
      4. 。。。
    4. 成功案例
      1. Linux 桌面环境 KDE
      2. WPS
      3. 谷歌地图
      4. VLC
      5. 虚拟机软件
  2. Qt项目创建
    1. 项目名称 不能有空格和中文
    2. 项目路径不能有中文路径
    3. 创建窗口三大基类
      1. QWidget
      2. QMainWindow
      3. QDialog
    4. Main函数中
      1. QApplication a  应用程序对象  在Qt中 有且仅有一个
      2. MyWidget w 窗口对象
      3. w.show() 函数显示窗口
      4. return  a.exec()进入消息循环机制,阻塞功能
    5. .pro文件
      1. QT       += core gui      //Qt包含的模块
      2. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets    //大于4版本  加入 widgets   模块
      3. TARGET = 01_QtFirst   //生成.exe程序的名称
      4. TEMPLATE = app        //模板 应用程序模板
      5. SOURCES += main.cpp\   //源文件
      6.         mywidget.cpp
      7. HEADERS  += mywidget.h  //头文件
  3. QPushButton按钮
    1. QPushButton * btn = new QPushButton;  创建按钮对象
    2. btn - >setParent(this) 设置父亲
    3. 设置显示文本 setText
    4. 移动    move
    5. 重置窗口大小  resize
    6. 设置固定窗口大小   setFixedSize
    7. 设置窗口标题   setWindowTitle
  4. Qt中的对象树
    1. 一定程度上简化了内存回收机制
    2. 当创建的对象 指定的父亲是由QObject或者Object派生的类时候,这个对象被加载到对象树上,当窗口关闭掉时候,树上的对象也都会被释放掉
  5. Qt中的坐标系
    1. x以右侧为正
    2. y以下侧为正
    3. 左上角是 0,0点
  6. Qt中信号和槽基本使用
    1. 需求:点击按钮关闭窗口
    2. 连接  connect ( 信号的发送者,发送的信号,信号的接受者,处理的槽函数)

  connect( myBtn , &MyPushButton::clicked ,this, &MyWidget::close);

    1. 测试  
  1. 自定义信号和槽
    1. 自定义信号 写在  signals下
      1. 返回值是void
      2. 只需要声明 不需要实现
      3. 可以有参数  可以发生重载
    2. 自定义槽函数 写在 public 或者全局函数 或者 public slot 或者lambda
      1.   返回值是void
      2.   需要声明 也需要有实现
      3.   可以有参数  可以发生重载
    3. 当信号和槽发生重载时候,需要利用函数指针明确指出函数地址
      1. void(Teacher:: *teacherSignal)(QString) = &Teacher::hungry;
    4. 将QString 转为 char *
      1.  .toUtf8()转为  QByteArray数据类型
      2.  .data() 转为 char * 类型
  2. 信号和槽拓展
    1. 信号是可以连接信号
    2. 可以断开信号和槽  disconnect
    3. 一个信号可以响应多个槽函数
    4. 多个信号可以连接同一个槽函数
    5. 信号和槽函数的参数类型 必须一一对应,信号的参数个数 可以多余槽函数的参数个数,反之不可以 , 参数类型要一一对应
  3. Qt4版本信号和槽写法
    1.   优势 :参数直观
    2.   劣势 :参数类型不做匹配检测
    3.   Qt4本质   SIGNAL("hungry(int)")SLOT("treat(QString)")
  4. Lambda表达式
    1. []()mutable  -> type {}组成
    2. []中可以加 =  &  a  &a … 推荐 使用 =
    3. () 形参列表
    4. {} 实现体
    5. mutable可以修改按值传递进来的拷贝
    6. -> type 代表lambda表达式返回值类型

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GSM/CDMA/VoLTE/VoIP通话

1.GSM(Global System for Mobile Communications) 本质是一种多址技术&#xff0c;将多个通话放入一段无线电频道的方法。特点是通过“时间划分”&#xff0c;称为时分多址。 2.CDMA(Code Division Multiple Access) 一种多址技术&#xff0c;将多个通话放入一段无线电频道的…

11_Redis经典五大类型源码及底层实现

Redis经典五大类型源码及底层实现 一、Redis数据类型的底层数据结构 SDS动态字符串双向链表压缩列表 zpilist哈希表 hashtable调表 skiplist整数集合 intset快速列表 quicklist紧凑列表 listpack 二、Redis源码地址 Github&#xff1a;https://github.com/redis/redis 三、…

Appium 2安装与使用java对Android进行自动化测试

文章目录 1、Appium 2.1安装1.1、系统要求1.2、安装Appium2.1服务1.3、安装UiAutomator2驱动1.4、安装Android SDK platform tools1.5、下载OpenJDK 2、Android自动代码例子2.1、安装Android自动化测试元素定位工具Appium Inspector2.2、编写android app自动化测试代码和使用ex…

Lemon8与中国各大社交平台的内容输出整合,将会掀起何种风浪?

近期,Lemon8迅速在北美地区展开了布局,短短几天的时间,下载量就冲到了美国APP下载总榜的前十,随后更是直登顶生活类APP首榜。作为字节跳动旗下的出海内容平台,一经问世后,就受到了大量用户的关注,并吸引了海外媒体以及营销人士的目光。那么Lemon8与中国各大社交平台的内容输出整…

机器学习笔记之优化算法(十六)梯度下降法在强凸函数上的收敛性

机器学习笔记之优化算法——梯度下降法在强凸函数上的收敛性 引言回顾&#xff1a;凸函数与强凸函数梯度下降法&#xff1a;凸函数上的收敛性分析 关于白老爹定理的一些新的认识梯度下降法在强凸函数上的收敛性收敛性定理介绍结论分析证明过程 引言 本节将介绍&#xff1a;梯度…

人工智能大模型加速数据库存储模型发展 行列混合存储下的破局

数据存储模型 ​专栏内容&#xff1a; postgresql内核源码分析手写数据库toadb并发编程toadb开源库 个人主页&#xff1a;我的主页 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 概述 在数据库的发展过程中&#xff0c;关…

【Linux】进程间通信之信号机制

文章目录 信号的概念信号的产生硬件产生&#xff08;按键盘中的按键&#xff09;软件产生kill函数kill命令abort函数raise函数 捕捉信号后的处理方式默认处理方式SIG_DFL忽略处理方式SIG_IGN自定义信号处理方式signal函数sigaciotn函数 信号的注册进程中的未决信号集&#xff0…

在python中通过调用dll来提高运行速度

1、前言 最近项目中需要录制键鼠命令&#xff0c;然后再通过注入的方式回放录制过程。一般来说&#xff0c;普通的一些点击命令完全可以通过python的一些包来完成键鼠模拟操作&#xff0c;比如通过pyautogui包。但是&#xff0c;鼠标移动过程中&#xff0c;如果采用频率很高的…

C++对象模型实验(clang虚函数表结构)

摘要&#xff1a;本科期间有对比过msvc&#xff0c;gcc&#xff0c;clang的内存布局&#xff0c;距今已经6-7年了&#xff0c;当时还是使用的c11。时间过得比较久了&#xff0c;这部分内容特别是内存对齐似乎C17发生了一些变化&#xff0c;因此再实践下C类模型。本文描述了C不同…

DuckDB Executor:物理计划构建Pipeline并执行(PipelineExecutor)

2023-03-20 duckdb-Push-Based Execution Model 如下SQL的物理计划执行 select 100(select 3), id from user where id (select id from score where id 1) Pipeline与MetaPipeline Pipeline是一串Op. MetaPipeline是pipeline组成的树 Executor构建MetaPipeline MetaPip…

【汇编语言】关于“段”的总结

文章目录 各种段三种段具体案例截图数据段、栈段、代码段同时使用不同段地址数据段、栈段、代码段同时使用一个段地址![在这里插入图片描述](https://img-blog.csdnimg.cn/45c299950ad949e3a90b7ed012b3a9ee.png) 各种段 1、基础 物理地址 段地址 x 16 偏移地址 2、做法 编…

Redis——主从复制+集群搭建(非哨兵)

主从复制 概念 主从复制&#xff0c;是指将一台Redis服务器的数据&#xff0c;复制到其他的Redis服务器。前者称为主节点(master/leader)&#xff0c;后者称为从节点(slave/follower); 数据的复制是单向的&#xff0c;只能由主节点到从节点。Master以写为主&#xff0c;Slave…

CentOS6.8图形界面安装Oracle11.2.0.1.0

Oracle11下载地址 https://edelivery.oracle.com/osdc/faces/SoftwareDelivery 一、环境 CentOS release 6.8 (Final)&#xff0c;测试环境&#xff1a;内存2G&#xff0c;硬盘20G&#xff0c;SWAP空间4G Oracle版本&#xff1a;Release 11.2.0.1.0 安装包&#xff1a;V175…

【C++奇遇记】构造函数 | 初始化列表

&#x1f3ac; 博客主页&#xff1a;博主链接 &#x1f3a5; 本文由 M malloc 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f384; 学习专栏推荐&#xff1a;LeetCode刷题集 数据库专栏 初阶数据结构 &#x1f3c5; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如…

LeetCode:Hot100python版本之回溯

回溯算法其实是纯暴力搜索。for循环嵌套是写不出的 组合&#xff1a;没有顺序 排列&#xff1a;有顺序 回溯法可以抽象为树形结构。只有在回溯算法中递归才会有返回值。 46. 全排列 78. 子集 17. 电话号码的字母组合 39. 组合总和 22. 括号生成 79. 单词搜索 ​​​​​​13…

剪枝基础与实战(3): 模型剪枝和稀疏化训练流程

Model Pruning 相关论文:Learning Efficient Convolutional Networks through Network Slimming (ICCV 2017) 考虑一个问题,深度学习模型里面的卷积层出来之后的特征有非常多,这里面会不会存在一些没有价值的特征及其相关的连接?又如何去判断一个特征及其连接是否有价值? …

Android学习之路(7) Frament

Fragment 表示应用界面中可重复使用的一部分。fragment 定义和管理自己的布局&#xff0c;具有自己的生命周期&#xff0c;并且可以处理自己的输入事件。fragment 不能独立存在。它们必须由 activity 或其他 fragment 托管。fragment 的视图层次结构会成为宿主的视图层次结构的…

2023国赛数学建模C题思路模型代码 高教社杯

本次比赛我们将会全程更新思路模型及代码&#xff0c;大家查看文末名片获取 之前国赛相关的资料和助攻可以查看 2022数学建模国赛C题思路分析_2022国赛c题matlab_UST数模社_的博客-CSDN博客 2022国赛数学建模A题B题C题D题资料思路汇总 高教社杯_2022国赛c题matlab_UST数模社…

【Keil软件 ST-Link下载问题】:提示ST-Link需要升级,但是升级之后会报错:Upgrade Error, Please try again.

项目场景&#xff1a; 报错&#xff1a; 平常一直使用J-link&#xff0c;一直没有问题&#xff0c;今天使用了一下ST-Link发现了问题&#xff0c;下载不进去。 并且提示我需要升级ST-Link&#xff0c;我按照规定的升级&#xff0c;但是依然报错。 下面是我的心路历程&#xff…

JDK中的Timer总结

目录 一、背景介绍二、思路&方案三、过程1.Timer关键类图2.Timer的基本用法3.结合面向对象的角度进行分析总结 四、总结五、升华 一、背景介绍 最近业务中使用了jdk中的Timer&#xff0c;通过对Timer源码的研究&#xff0c;结合对面向对象的认识&#xff0c;对Timer进行针…