当前位置: 首页 > news >正文

C++ Qt 学习(一):Qt 入门

  • Qt6 安装教程

0. 基础知识

0.1 qmake 和 cmake 对比

  • qmake:qt 独有的代码构建工具
  • cmake:C++ 通用的代码构建工具,绝大部分 C++ 开源项目都使用 cmake 管理代码
  • qt 项目,没有特殊要求,使用 qmake 即可

0.2 Qt 3 个窗口类的区别

  • QMainWindow
    • 包含菜单栏、工具栏、状态栏
    • QMainWindow 使用的场景不多
  • QWidget
    • 一个普通的窗口,不包含菜单栏、状态栏,除了登录界面
    • 新建项目时建议使用 Qwidget,因为大部分的窗口可能都要做成无边框窗口,需要自定义标题栏,实现拉伸等
  • QDialog
    • 对话框,常用来做登录窗口、弹出窗口 (例如设置界面)

1. 图片查看软件

在这里插入图片描述

1.1 main.cpp

#include "widget.h"#include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

1.2 widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:void open1();  // 基础版本void open2();  // 记住上次打开的路径,并指定默认的路径为 文档/图片void open3();  // 图片自适应显示private slots:void on_btnOpen_clicked();private:Ui::Widget *ui;
};
#endif // WIDGET_H

1.3 widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#include <QSettings>  // 用于读取和写入应用程序的设置和配置信息
#include <QDebug>
#include <QStandardPaths>
#include <memory>     // 智能指针Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);ui->label_image->clear();
}Widget::~Widget() {delete ui;
}void Widget::open1() {// QFileDialog::getOpenFileName() 用于显示一个打开文件对话框,并返回用户选择的文件路径// 参数:指向当前窗口的指针 this,打开的窗口标题,默认打开路径,文件类型过滤器QString filename = QFileDialog::getOpenFileName(this, "请选择图片", "D:/", "图片(*.png *jpg);");if(filename.isEmpty()) {return;}ui->lineEdit_path->setText(filename);  // 显示图片路径ui->label_image->setPixmap((QPixmap(filename)));  // 显示图片
}// 记住上次打开的路径,并指定默认的路径为 文档/图片
void Widget::open2() {// qApp->applicationDirPath() 用于获取当前应用程序所在的目录路径// "/config/Setting.ini" 是一个固定的字符串表示配置文件的路径QString config_path = qApp->applicationDirPath() + "/config/Setting.ini";qDebug() << config_path;// 使用智能指针创建了一个 QSettings 对象,并使用指定的配置文件路径和格式进行初始化// QSettings::IniFormat 是一个枚举值,用于指定配置文件的格式,此处采用的是 ini 格式的配置文件// 通过 pIniSet 指针调用 value() 函数来获取指定键的值,并将其转换为 QString 类型std::unique_ptr<QSettings> pIniSet(new QSettings(config_path, QSettings::IniFormat));QString lastPath = pIniSet->value("/LastPath/path").toString();// 设置默认读取路径为 windows 下 图片 目录if(lastPath.isEmpty()) {lastPath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);}QString filename = QFileDialog::getOpenFileName(this, "请选择图片", lastPath, "图片(*.png *jpg);");if(filename.isEmpty()) {return;}ui->lineEdit_path->setText(filename);ui->label_image->setPixmap((QPixmap(filename)));// 找到给定文件名(filename)中最后一个斜杠"/"的位置int end = filename.lastIndexOf("/");// 提取文件名中最后一个斜杠"/"之前的部分,即路径部分QString _path = filename.left(end);// 将键 "/LastPath/path" 的值设置为 _pathpIniSet->setValue("/LastPath/path", _path);qDebug() << _path;
}// 图片自适应显示
void Widget::open3() {QString config_path = qApp->applicationDirPath() + "/config/Setting.ini";qDebug() << config_path;std::unique_ptr<QSettings> pIniSet(new QSettings(config_path, QSettings::IniFormat));QString lastPath = pIniSet->value("/LastPath/path").toString();if(lastPath.isEmpty()) {lastPath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);}QString filename = QFileDialog::getOpenFileName(this, "请选择图片", lastPath, "图片(*.png *jpg);");if(filename.isEmpty()) {return;}ui->lineEdit_path->setText(filename);// 图片自适应显示std::unique_ptr<QPixmap> pix(new QPixmap(filename));  // 通过给定的文件名(filename)加载图像数据// 将加载的图像按照 ui->label_image 控件的大小进行缩放// Qt::KeepAspectRatio:保持图像的纵横比例不变pix->scaled(ui->label_image->size(), Qt::KeepAspectRatio);ui->label_image->setScaledContents(true);  // 当图像大于控件大小时,将自动缩放以适应控件的大小ui->label_image->setPixmap(*pix);  // 设置 ui->label_image 控件的图像为加载并缩放后的图像int end = filename.lastIndexOf("/");QString _path = filename.left(end);pIniSet->setValue("/LastPath/path", _path);qDebug() << _path;
}void Widget::on_btnOpen_clicked() {//open1();//open2();open3();
}

1.4 widget.ui

在这里插入图片描述

2. C++ lambda 函数详解

  • C++ lambda 表达式的本质就是重载了 operator(),lambda 是一个类,在调用时会进行编译展开,因此 lambda 表达式对象其实就是一个匿名的 functor,所以 lambda 表达式也叫匿名函数对象
    • Qt 槽函数可以使用 lambda 函数来写
  • C++ 中 lambda 表达式的构成
    [捕获列表](形参列表) mutable 异常列表->返回类型  {函数体
    }
    
    • 捕获列表:捕获外部变量,捕获的变量可以在函数体中使用,可以省略,即不捕获外部变量
    • 形参列表:和普通函数的形参列表一样。可省略,即无参数列表
    • mutable:如果有,则表示在函数体中可以修改捕获变量,根据具体需求决定是否需要省略
    • 异常列表:noexcept /throw(…),和普通函数的异常列表一样,可省略,即代表可能抛出任何类型的异常
    • 返回类型:和函数的返回类型一样。可省略,如省略,编译器将自动推导返回类型
    • 函数体:代码实现,可省略,但是没意义
  • 捕获方式
    • 值捕获:不能在 lambda 表达式中修改捕获变量的值
    • 引用捕获:使用引用捕获一个外部变量,需在捕获列表变量前面加上一个引用说明符 &
    • 隐式捕获
    #include <iostream>using namespace std;int main() {// 1、值捕获int value = 100;auto f = [value](int a, int b)->int {//value++;  // 不能在 lambda 表达式中修改捕获变量的值return a + b + value;};cout << f(1, 2) << endl;// 2、引用捕获auto f2 = [&value](int a, int b)->int {value++;return a + b;};cout << f2(1, 3) << endl;cout << "value = " << value << endl;// 3、隐式捕获// = 值捕获// & 引用捕获int age = 123;auto f3 = [&](int a, int b)->int {value++;age++;return a + b;};return 0;
    }
    

3. 槽函数的常见写法

  • Qt 4 写法

    connect(ui->btnOpen, SIGNAL(clicked), this, SLOT(open()));
    
    • 不推荐这种写法,如果 SIGNAL写错了,或者信号名字、槽函数名字写错了编译器检查不出来,导致程序无响应,引起不必要的误解
  • Qt 5 写法

    connect(ui.btnOpen, QPushButton::clicked, this, &Widget::open);
    
    • 推荐使用这种写法
  • lambda 函数表达式写法

    connect(ui.btnOpen, &QPushButton::clicked, [=](){// 具体代码实现
    });
    
    • 适用于 slot 代码比较少的逻辑
  • 直接法

    void on_控件名_信号名();
    
    • 这种不用 connect,Qt 自动连接

4. 自定义信号及参数注册

4.1 跨 UI 发送自定义信号

在这里插入图片描述

  • 如何自定义信号

    • 使用signals声明
    • 返回值是void
    • 在需要发送的地方使用下述方法进行发送
      • emit 信号名字(参数);
    • 在需要链接的地方使用connect进行链
  • widget.h

    #ifndef WIDGET_H
    #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
    namespace Ui { class Widget; }
    QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_btnOpen_clicked();private:Ui::Widget *ui;
    };
    #endif // WIDGET_H
    
  • dialog.h

    • 跨 UI 发送:New File --> Qt Designer Form Class --> Dialog without Buttons
    #ifndef DIALOG_H
    #define DIALOG_H#include <QDialog>namespace Ui { class Dialog; }class Dialog : public QDialog {Q_OBJECTpublic:explicit Dialog(QWidget *parent = nullptr);~Dialog();private slots:void on_btnAdd_clicked();signals:void sig_addOne(int value);private:Ui::Dialog *ui;
    };#endif // DIALOG_H
    
  • widget.cpp

    #include "widget.h"
    #include "ui_widget.h"
    #include "dialog.h" // 跨 UI 头文件Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);
    }Widget::~Widget() {delete ui;
    }void Widget::on_btnOpen_clicked() {Dialog dlg;// 使用 lambda 函数编写槽函数connect(&dlg, &Dialog::sig_addOne, [=](int value) {ui->lineEdit->setText(QString::number(value));});dlg.exec();  // 需放在 connect 后,因为此行为事件循环会阻塞 UI
    }
    
  • dialog.cpp

    #include "dialog.h"
    #include "ui_dialog.h"Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) {ui->setupUi(this);
    }Dialog::~Dialog() {delete ui;
    }void Dialog::on_btnAdd_clicked() {static int value = 100;emit sig_addOne(value++); // 实现跨 UI 自加操作
    }
    

4.2 跨线程发送自定义信号

Qt 的子线程无法直接修改 ui,需要发送信号到 ui 线程进行修改

  • widget.h

    #ifndef WIDGET_H
    #define WIDGET_H#include <QWidget>
    #include "childthread.h"QT_BEGIN_NAMESPACE
    namespace Ui { class Widget; }
    QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_btnUpdate_clicked();void showInfo(Score s);private:Ui::Widget *ui;
    };
    #endif // WIDGET_H
    
  • widget.cpp

    #include "widget.h"
    #include "ui_widget.h"
    #include <QDebug>Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);qDebug() << "ui thread id = " << QThread::currentThreadId();
    }Widget::~Widget() {delete ui;
    }void Widget::on_btnUpdate_clicked() {ChildThread *ch = new ChildThread();// 以下实现还是在子线程中(不在 ui 线程中),无法直接修改 ui
    //    connect(ch, &ChildThread::sig_SendToUI, [=](Score s) {
    //        string info = s.name + "id = " + to_string(s.id) + " age = " + to_string(s.age);
    //        ui->lineEdit->setText(QString::fromStdString(info));
    //        // 用于验证 slot 与 ui 下是否同属一个线程(id)
    //        // 结果表明此处的 slot 与子线程的 run() 同属一个线程(id)
    //        qDebug() << "slot thread id = " << QThread::currentThreadId();
    //    });// 以下实现在 ui 线程 (主线程) 中,可以直接修改 uiconnect(ch, &ChildThread::sig_SendToUI, this, &Widget::showInfo);ch->start();
    }void Widget::showInfo(Score s) {qDebug() << "ui thread id2 = " << QThread::currentThreadId();string info = s.name + "id = " + to_string(s.id) + " age = " + to_string(s.age);ui->lineEdit->setText(QString::fromStdString(info));
    }
    
  • childthread.h

    #ifndef CHILDTHREAD_H
    #define CHILDTHREAD_H#include <QThread>
    #include <string>using namespace std;struct Score {string name;int id;int age;
    };class ChildThread : public QThread {Q_OBJECTpublic:ChildThread();protected:void run() override;signals:void sig_SendToUI(Score score);
    };#endif // CHILDTHREAD_H
    
  • childthread.cpp

    #include "childthread.h"
    #include <QDebug>ChildThread::ChildThread() {// 非基础类型参数需要注册qRegisterMetaType<Score>("Score");qRegisterMetaType<string>("string");
    }void ChildThread::run() {qDebug() << "run thread id = " << QThread::currentThreadId();Score s;s.name = "jack";s.id = 1001;s.age = 26;emit sig_SendToUI(s);  // 发送信号
    }
    

4.3 处理信号重名问题

  • 例如 QComboBox 的信号

    Q_SIGNALS:void currentIndexChanged(int index);void currentIndexChanged(const QString &);
    
  • 解决方案

    // 错误写法
    connect(ui->comboBox, &QComboBox::currentIndexChanged, this, &Widget::onIndex);// 解决方案一
    connect(ui->comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onIndex(int)));// 解决方案二
    connect(ui->comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &Widget::onIndex);
    

5. connect 函数详解

template <typename Func1, typename Func2>
static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender,Func1 signal,const typename QtPrivate::FunctionPointer<Func2>::Object *receiver,Func2 slot,Qt::ConnectionType type = Qt::AutoConnection)
enum ConnectionType {AutoConnection,DirectConnection,QueuedConnection,BlockingQueuedConnection,UniqueConnection =  0x80,SingleShotConnection = 0x100,
};
  • AutoConnection

    • 默认连接方式,如果接收方在发出信号的线程中,使用 Qt::DirectConnection
    • 否则使用 Qt::QueuedConnection,在发出信号时确定连接类型
    • Qt 中默认使用 AutoConnection,所以平时写信号槽时都是 4 个参数
  • DirectConnection

    • 当发出信号时,插槽立即被调用,槽在发送信号的线程中执行
  • QueuedConnection

    • 当控制返回到接收方线程的事件循环时调用槽,槽在接收方的线程中执行
  • BlockingQueuedConnection

    • 与 Qt::QueuedConnection 相同,只是发送信号的线程会阻塞,直到槽返回
    • 如果接收方存在于发送信号的线程中,则不能使用此连接,否则应用程序将产生死锁
  • UniqueConnection

    • 这是一个可以使用按位 OR 与上述任何一种连接类型组合的标志,当 Qt::UniqueConnection 被设置时,如果连接已经存在,QObject::connect() 将失败 (例如,如果相同的信号已经连接到相同的对象对的插槽)

6. Qt 信号槽与 MOC

  • moc 全称是 Meta-Object Compiler,也就是 “元对象编译器”
    • Qt 程序在交由标准编译器编译之前,先要使用 moc 分析 C++ 源文件
    • 如果发现在一个头文件中包含了宏 Q_OBJECT,则会生成另外一个 C++ 源文件,这个源文件中包含了 Q_OBJECT 宏的实现代码,这个新的文件名是原文件名前面加上 moc_ 构成,这个新的文件同样将进入编译系统,最终被链接到二进制代码中去。因此,这个新的文件不是 “替换” 掉旧的文件,而是与原文件一起参与编译
    • 另外,还可看出:moc 的执行是在预处理器之前,因为预处理器执行之后,Q_OBJECT 宏就不存在了

    可以这么理解,moc 把 Qt 中一些不是 C++ 的关键字做了解析,让 C++ 编译器认识,例如:slots, signals,emit 等,moc 会把这些重新编译解析

7. Qt 内存管理机制

  • C++ 派生类

    • 构造顺序:先执行基类的构造函数,再执行派生类的构造函数
    • 析构顺序:先执行派生类的析构函数,再执行基类的析构函数
  • Qt 半内存管理机制

    • QObject 及其派生类的对象,如果其 parent 非 0,那么其 parent 析构时会析构该对象
    • QWidget 及其派生类的对象,可以设置 Qt::WA_DeleteOnClose 标志位,当 close 时会调用 QWidgetPrivate::close_helper,进而调用 deleteLater 析构该对象

8. 解决 Qt 中文乱码问题

  • 粘贴别人的代码时,首先在记事本里复制一遍,再粘贴到 QtCreator

  • 使用 u8

    • ui.pushButton->setText (u8"你好")
  • 不使用 QtCreator开发,直接使用 vs2019

  • 其他设置

    • QtCreator — 选项 — 文本编辑器 — UTF8 BOM 总是删除
    • #pragma execution_character_set(“utf-8”)

相关文章:

C++ Qt 学习(一):Qt 入门

Qt6 安装教程 0. 基础知识 0.1 qmake 和 cmake 对比 qmake&#xff1a;qt 独有的代码构建工具cmake&#xff1a;C 通用的代码构建工具&#xff0c;绝大部分 C 开源项目都使用 cmake 管理代码qt 项目&#xff0c;没有特殊要求&#xff0c;使用 qmake 即可 0.2 Qt 3 个窗口类的…...

高性能消息中间件 - Kafka3.x(三)

文章目录 高性能消息中间件 - Kafka3.x&#xff08;三&#xff09;Kafka Broker ⭐Kafka Broker概念Zookeeper&#xff08;新版本可以不使用zk了&#xff09;⭐Zookeeper的作用 Kafka的选举1&#xff1a;Broker选举Leader⭐Broker核心参数⭐案例&#xff1a;服役新节点和退役旧…...

【八】Linux成神之路

Linux成神之路 简介&#xff1a;最近梳理了一下自己linux系统的学习历程&#xff0c;感觉整个成长过程就很顺利&#xff0c;并没有走弯路&#xff0c;于是想着可以不可以把自己linux系统学习的路线记录下来&#xff0c;能够在大家成长的路上有一点帮助&#xff0c;就在这样的一…...

功能测试用例,需要详细到什么程度?

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…...

VScode远程连接错误:进程试图写入不存在的管道

使用VScode连接树莓派时&#xff0c;出现远程连接错误&#xff1a;进程试图写入不存在的管道 解决方案&#xff1a; &#xff08;1&#xff09;可以进入config所在文件夹&#xff0c;删除文件 &#xff08;2&#xff09;无法解决的化尝试下述方法 输入 Remotting-SSH:Settin…...

Python测试之Pytest详解

概要 当涉及到python的测试框架时&#xff0c;pytest是一个功能强大且广泛应用的第三方库。它提供简洁而灵活的方式来编写和执行测试用例&#xff0c;并具有广泛的应用场景。下面是pytest的介绍和详细使用说明&#xff1a; pytest是一个用于python单元测试的框架&#xff0c;它…...

uni-app微信小程序打开第三方地图

需求 小程序中有个按钮点击以后会调用手机中第三方地图进行导航。参数 位置信息 经度 与纬度。 实现方法 uni.openLocation({latitude: Number(地址纬度),longitude: Number(地址经度),name: 地址名称,address: 地址详情,success: function (res) {console.log(打开系统位置地…...

Android NDK开发详解之NDK 使用入门

Android NDK开发详解之NDK 使用入门 下载 NDK 和工具创建或导入原生项目 原生开发套件 (NDK) 是一套工具&#xff0c;使您能够在 Android 应用中使用 C 和 C 代码&#xff0c;并提供众多平台库&#xff0c;您可使用这些平台库管理原生 activity 和访问实体设备组件&#xff0c;…...

nmap指纹识别要点以及又快又准之方法

nmap指纹识别要点以及又快又准之方法 一. 前言:二. nmap识别实验:一. 实验一:IP配置:空间配置:扫描结果:详细输出二. 实验二:IP配置:空间配置:扫描结果:详细输出三. 实验三:IP配置:空间配置:扫描结果:详细输出四. 实验四:IP...

Rust编程基础之6大数据类型

1.Rust数据类型 在 Rust 中, 每一个值都属于某一个 数据类型&#xff08;data type&#xff09;, 这告诉 Rust 它被指定为何种数据&#xff0c;以便明确数据处理方式。我们将看到两类数据类型子集&#xff1a;标量&#xff08;scalar&#xff09;和复合&#xff08;compound&a…...

06 MIT线性代数-线性无关,基和维数Independence, basis, and dimension

1. 线性无关 Independence Suppose A is m by n with m<n (more unknowns than equations) Then there are nonzero solutions to Ax0 Reason: there will be free variables! A中具有至少一个自由变量&#xff0c;那么Ax0一定具有非零解。A的列向量可以线性组合得到零向…...

Kubernetes 概述以及Kubernetes 集群架构与组件

目录 Kubernetes概述 K8S 是什么 为什么要用 K8S K8S 的特性 Kubernetes 集群架构与组件 核心组件 Master 组件 Node 组件 ​编辑 Kubernetes 核心概念 常见的K8S按照部署方式 Kubernetes概述 K8S 是什么 K8S 的全称为 Kubernetes,Kubernetes 是一个可移植、可扩…...

GZ035 5G组网与运维赛题第9套

2023年全国职业院校技能大赛 GZ035 5G组网与运维赛项&#xff08;高职组&#xff09; 赛题第9套 一、竞赛须知 1.竞赛内容分布 竞赛模块1--5G公共网络规划部署与开通&#xff08;35分&#xff09; 子任务1&#xff1a;5G公共网络部署与调试&#xff08;15分&#xff09; 子…...

使用Jasypt3.0.3版本对SpringBoot配置文件加密

时间 2023-11-01 使用Jasypt3.0.3版本对SpringBoot配置文件加密 目录 引入依赖使用密钥生成密文配置yml验证是否自动解密 引入依赖 <!--yml 文件加解密--><dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-b…...

生成一篇博客,详细讲解springboot的单点登录功能,有流程图,有源码demo

SpringBoot是目前非常流行的一个Java开发框架&#xff0c;它以简洁的配置和快速的开发效率著称。在实际应用中&#xff0c;单点登录是一个非常重要的功能&#xff0c;它可以让用户在多个应用系统中使用同一个账号登录&#xff0c;提高用户体验和安全性。本文将详细讲解如何在Sp…...

Hadoop、Hive安装

一、 工具 Linux系统&#xff1a;Centos&#xff0c;版本7.0及以上 JDK&#xff1a;jdk1.8 Hadoop&#xff1a;3.1.3 Hive&#xff1a;3.1.2 虚拟机&#xff1a;VMware mysql&#xff1a;5.7.11 工具下载地址: https://pan.baidu.com/s/1JYtUVf2aYl5–i7xO6LOAQ 提取码: xavd…...

PHP自定义函数--输入起始日期和解算日期返回日期差几天和 上一个周期的起始结束日期

/** 日期差几天* param beginDate:2018-01-26 endDatee:2018-01-26* return int days* */ function dateDiff($beginDate, $endDate) {$diff date_diff(date_create($beginDate), date_create($endDate))->format(%R%a);return (int)$diff; }/** 返回上一周期的起始和结束日…...

.net 7 上传文件踩坑

(Name “file”) 没加上这个传不进文件 /// <summary>/// 上传单个文件/// </summary>/// <param name"formFile"></param>/// <returns></returns>[HttpPost("UploadFiles")][FunctionAttribute(MuType.Btn, "…...

C++基础算法④——排序算法(快速、归并附完整代码)

快速排序 快速排序是对冒泡排序的一种改进。 它的基本思想是:通过一趟排序将待排记录分割成独立的两部分&#xff0c;其中一部分记录的关键字均比另一部分记录的关键字小&#xff0c;则可分别对这两部分记录继续进行快速排序&#xff0c;以达到整个序列有序。 假设我们现在对 …...

高防CDN如何在防护cc上大显神通

高级防御CDN&#xff08;Content Delivery Network&#xff09;在对抗CC&#xff08;HTTP Flood&#xff09;攻击方面扮演着关键的角色&#xff0c;具备以下重要职能和作用&#xff1a; 流量分散&#xff1a;CC攻击的目标是通过大规模的HTTP请求使服务器过载&#xff0c;从而导…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...