qt-C++笔记之QThread使用

qt-C++笔记之QThread使用

——2024-05-26 下午

在这里插入图片描述

在这里插入图片描述

code review!

参考博文:
qt-C++笔记之使用QtConcurrent异步地执行槽函数中的内容,使其不阻塞主界面
qt-C++笔记之QThread使用

文章目录

  • qt-C++笔记之QThread使用
    • 一:Qt中几种多线程方法
      • 1.1. 使用 `QThread` 和 Lambda
      • 1.2. 使用 `QThread::create()`
      • 1.3. 继承 `QThread` 并重写 `run()`
      • 1.4. 使用 `QObject` 派生类与 `QThread`
      • 1.5. 使用 `QtConcurrent::run()`
      • 总结
    • 二.方法一:继承QThread并重写其run()方法
      • 2.1.代码一:运行全局纯函数
      • 2.2.代码二:运行全局纯函数
      • 2.3.代码一和代码二的区别
        • 2.3.1 带`input`参数的构造函数
        • 2.3.2. 带`input`和`parent`参数的构造函数
        • 2.3.3 总结
      • 2.4.代码三:直接在run()方法中写运行逻辑
      • 2.5.代码四:直接在run()方法中写运行逻辑,并在QCoreApplication::quit()前执行一些打印
      • 2.6.代码五:通过继承QThread的方式来运行一个纯函数,并将参数通过类的成员变量传递给这个函数
      • 2.7.代码六:通过继承QThread的方式来运行一个纯函数,并将参数通过类的成员变量传递给这个函数
    • 三.方法二:将任务放在QObject派生类中,并`moveToThread()`在QThread中运行这个QObject
      • 3.1. 代码一:运行成员函数例程,让 Worker 类继承自 QObject,然后使用一个 QThread 实例来在另一个线程中运行这个 Worker 对象
      • 3.2. 代码二:运行成员函数例程,让 Worker 类继承自 QObject,然后使用一个 QThread 实例来在另一个线程中运行这个 Worker 对象
    • 四.方法三:直接使用 QThread 和 Lambda
    • 五.方法四:`QThread::create(Qt 5.10 及以上)`
      • 5.1.提要
        • 5.1.1.QThread::create()代码一
        • 5.1.2.QThread::create()代码二
    • 六.方法五:`QtConcurrent::run()`

一:Qt中几种多线程方法

五种不同的多线程实现方法在Qt中的特点和适用场景:

方法描述优点缺点适用场景
直接使用 QThread 和 Lambda使用 QThread 对象和信号槽连接一个lambda表达式来执行代码。简单快速;灵活定义启动行为。精细控制线程较少;线程复用不便。快速实现简单的后台任务,不需要复用线程。
使用 QThread::create()使用 QThread::create() 创建并自动启动线程来执行函数或lambda。极简代码;自动线程管理。对线程的控制较为有限;不易于复用。适合快速启动一次性后台任务,不需要线程间交互。
继承 QThread 并重写 run()通过继承 QThread 并重写其 run() 方法来定义线程行为。完全控制线程行为;能够处理复杂逻辑。实现复杂;易误用(如直接操作GUI)。需要精细控制线程行为或有复杂线程逻辑的场景。
使用 QObject 派生类与 QThread创建 QObject 派生类,并在移至 QThread 的对象上执行任务。分离工作和线程管理;完全的信号和槽支持。设置相对繁琐;代码量较多。需要线程频繁与主线程通信或任务较为复杂的场景。
使用 QtConcurrent::run()使用Qt并发模块的 QtConcurrent::run() 在线程池中运行函数或成员函数。简单易用;自动管理线程池;减少资源消耗。对线程控制较少;不适合特定线程管理需求。适用于执行独立的并发任务,不需要细粒度线程控制。

1.1. 使用 QThread 和 Lambda

这种方法直接使用 QThread 的实例,并通过信号和槽系统将lambda表达式绑定至 QThread::started 信号。这种方法允许灵活地定义线程开始时执行的代码,而不需创建额外的类或使用 QtConcurrent。它适合快速简单的线程使用,尤其是当你不需要频繁与主线程通信或管理复杂的线程生命周期时。

1.2. 使用 QThread::create()

QThread::create() 是Qt 5.10引入的一个便捷函数,它基本上是创建线程与绑定任务的简化版。你只需要提供一个函数或lambda表达式,QThread::create() 会自动创建线程并在启动线程时执行这个函数。

auto thread = QThread::create([](){// 执行一些任务
});
thread->start();

这种方法的优点是极其简单,但它通常不适用于需要复杂线程管理或多次复用线程的场景。

1.3. 继承 QThread 并重写 run()

这是一种更传统的方法,通过继承 QThread 并重写其 run() 方法实现。这种方法提供了最大的灵活性,允许你控制线程的准确行为,但也需要更多的代码和复杂的错误处理。

class WorkerThread : public QThread
{
protected:void run() override {// 执行任务}
};

1.4. 使用 QObject 派生类与 QThread

这是Qt推荐的多线程使用方式。你创建一个 QObject 派生类来封装工作任务,然后将这个对象的实例移动到 QThread 中。

class Worker : public QObject
{Q_OBJECT
public slots:void doWork() {// 执行任务}
};QThread *thread = new QThread();
Worker *worker = new Worker();
worker->moveToThread(thread);
connect(thread, &QThread::started, worker, &Worker::doWork);
thread->start();

这种方法适合需要线程与主线程频繁交互的场景,因为它完全兼容Qt的信号与槽机制。

1.5. 使用 QtConcurrent::run()

QtConcurrent::run() 是处理并发运算的另一种高级方法,它可以非常方便地在后台线程池中运行函数或成员函数。

QtConcurrent::run([](){// 执行某些操作
});

这种方法非常适合不需要细粒度控制线程行为的场景,且可以自动管理线程池,避免创建和销毁线程的开销。

总结

  • 直接使用 QThread 和 Lambda:适合快速、一次性的简单后台任务。
  • 使用 QThread::create():简化版的线程创建和任务绑定,适合不需要复用线程的场景。
  • 继承 QThread:适用于需要完全控制线程行为的复杂场景。
  • 使用 QObject 派生类与 QThread:Qt推荐的方式,适合需要线程间频繁通信的场景。
  • 使用 QtConcurrent::run():适用于简单并发任务,自动线程池管理,减少资源消耗。

二.方法一:继承QThread并重写其run()方法

2.1.代码一:运行全局纯函数

#include <QCoreApplication>
#include <QThread>
#include <QDebug>// 纯函数的定义,这个函数只进行计算并返回结果,不涉及任何的状态修改
int pureFunction(int x) {return x * x;
}// 创建一个线程类,用于运行纯函数
class WorkerThread : public QThread {
public:WorkerThread(int input) : inputValue(input) {}protected:void run() override {int result = pureFunction(inputValue);qDebug() << "计算结果:" << result;}private:int inputValue;
};int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);// 初始化一个线程对象,传入参数5WorkerThread thread(5);// 连接线程的finished信号到QCoreApplication的quit槽,确保应用程序在线程结束后退出QObject::connect(&thread, &QThread::finished, &a, &QCoreApplication::quit);// 启动线程thread.start();// 进入事件循环return a.exec();
}

运行

计算结果: 25

2.2.代码二:运行全局纯函数

#include <QCoreApplication>
#include <QThread>
#include <QDebug>// 全局纯函数
void globalPureFunction(int param) {qDebug() << "运行在线程:" << QThread::currentThreadId();qDebug() << "接收到的参数:" << param;// 模拟一些处理过程QThread::sleep(2); // 假装我们在做一些耗时的工作qDebug() << "处理完成";
}// 线程类
class WorkerThread : public QThread {int m_param;
public:WorkerThread(int param, QObject *parent = nullptr) : QThread(parent), m_param(param) {}protected:void run() override {globalPureFunction(m_param); // 在新线程中调用全局纯函数}
};// 主函数
int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);int inputValue = 42; // 示例参数值WorkerThread *thread = new WorkerThread(inputValue);thread->start(); // 启动线程QObject::connect(thread, &QThread::finished, thread, &QObject::deleteLater);QObject::connect(thread, &QThread::finished, &a, &QCoreApplication::quit);return a.exec();
}

运行

运行在线程: 0x7fd2ea57f700
接收到的参数: 42
处理完成

2.3.代码一和代码二的区别

在Qt中,处理QThread和其他继承自QObject的类时,构造函数中的parent参数非常关键,它影响对象的内存管理和事件传递机制。让我们比较一下这两种构造函数的定义和它们的实际用途:

2.3.1 带input参数的构造函数
WorkerThread(int input) : inputValue(input) {}

这个构造函数只接受一个input参数,并初始化成员变量inputValue。这里没有显式地处理parent参数:

  • 作用:初始化inputValue
  • 内存管理:这个WorkerThread对象的生命周期需要显式管理(比如通过在堆上创建和删除,或者确保其作用域在使用中不会结束),因为没有父对象来自动管理它。
  • 适用场景:当你不需要将线程对象的生命周期与其他Qt对象关联时,或者当你想要通过代码显式管理线程的生命周期时使用。
2.3.2. 带inputparent参数的构造函数
WorkerThread(int input, QObject *parent = nullptr) : QThread(parent), inputValue(input) {}

这个构造函数接受一个input参数和一个可选的parent参数,默认为nullptr。它在初始化列表中调用了QThread的构造函数,传递了parent参数:

  • 作用:初始化inputValue并设置父对象。
  • 内存管理:如果指定了父对象(parent不为nullptr),这个WorkerThread对象的生命周期将由其父对象自动管理(父对象销毁时,它也会被销毁)。如果parentnullptr,则其生命周期需要手动管理。
  • 适用场景:当你希望线程的生命周期与某个Qt对象(如窗口或其他组件)绑定时使用。这样可以简化内存管理,使线程的生命周期与其父对象相匹配。
2.3.3 总结

添加parent参数的版本提供了更灵活的内存管理选项,允许线程对象以树形层次结构中的一部分被管理,这对于复杂的Qt应用程序来说非常有用。没有parent参数的版本则简单、直接,更适合生命周期管理相对明确或简单的场合。在实际应用中,选择哪种方式取决于你的具体需求和线程管理策略。

2.4.代码三:直接在run()方法中写运行逻辑

#include <QCoreApplication>
#include <QThread>
#include <iostream>// WorkerThread 类,继承自 QThread
class WorkerThread : public QThread
{
public:WorkerThread(QObject *parent = nullptr) : QThread(parent) {}// 重载 run 方法void run() override {// 纯函数任务内容for (int i = 0; i < 10; ++i) {std::cout << "工作线程运行中: " << i << std::endl;QThread::sleep(1); // 模拟耗时操作,每次循环暂停1秒}std::cout << "工作线程结束运行。" << std::endl;}
};int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 创建 WorkerThread 对象WorkerThread thread;// 连接线程完成信号到退出槽,确保线程完成后应用程序退出QObject::connect(&thread, &WorkerThread::finished, &a, &QCoreApplication::quit);// 启动线程thread.start();// 进入 Qt 事件循环return a.exec();
}

运行

工作线程运行中: 0
工作线程运行中: 1
工作线程运行中: 2
工作线程运行中: 3
工作线程运行中: 4
工作线程运行中: 5
工作线程运行中: 6
工作线程运行中: 7
工作线程运行中: 8
工作线程运行中: 9
工作线程结束运行。

2.5.代码四:直接在run()方法中写运行逻辑,并在QCoreApplication::quit()前执行一些打印

#include <QCoreApplication>
#include <QThread>
#include <QDebug>// 纯函数,作为线程任务
void runTask() {for (int i = 0; i < 10; ++i) {QThread::sleep(1); // 模拟耗时任务qDebug() << "工作在线程 " << QThread::currentThreadId() << " 中执行: " << i;}
}// 自定义的线程类
class TaskThread : public QThread {Q_OBJECT // 添加 Q_OBJECT 宏以支持信号和槽
public:TaskThread(QObject *parent = nullptr) : QThread(parent) {}protected:void run() override {runTask(); // 在新线程中运行纯函数emit taskCompleted(); // 发射任务完成信号}signals:void taskCompleted();
};int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);TaskThread thread;QObject::connect(&thread, &TaskThread::taskCompleted, &a, [&]() {qDebug() << "任务完成,信号在主线程 " << QThread::currentThreadId() << " 中被处理";QCoreApplication::quit(); // 完成后退出程序});qDebug() << "主线程ID: " << QThread::currentThreadId();thread.start(); // 启动线程return a.exec();
}#include "main.moc" // 如果你不是使用 qmake,确保 moc 处理这个文件

运行

主线程ID:  0x7f7e73b0d780
工作在线程  0x7f7e6ef9d700  中执行:  0
工作在线程  0x7f7e6ef9d700  中执行:  1
工作在线程  0x7f7e6ef9d700  中执行:  2
工作在线程  0x7f7e6ef9d700  中执行:  3
工作在线程  0x7f7e6ef9d700  中执行:  4
工作在线程  0x7f7e6ef9d700  中执行:  5
工作在线程  0x7f7e6ef9d700  中执行:  6
工作在线程  0x7f7e6ef9d700  中执行:  7
工作在线程  0x7f7e6ef9d700  中执行:  8
工作在线程  0x7f7e6ef9d700  中执行:  9
任务完成,信号在主线程  0x7f7e73b0d780  中被处理

2.6.代码五:通过继承QThread的方式来运行一个纯函数,并将参数通过类的成员变量传递给这个函数

#include <QCoreApplication>
#include <QThread>
#include <QDebug>// 纯函数,有传参
int square(int x) {return x * x;
}// 继承QThread的类,重写run()函数
class MyThread : public QThread {
protected:void run() override {// 调用纯函数,并传参int result = square(x);qDebug() << "Result:" << result;}public:int x;
};int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);// 创建MyThread对象MyThread thread;// 在main函数中声明参数,并传入MyThread对象int param = 10;thread.x = param;// 启动MyThread对象thread.start();// 等待MyThread对象结束thread.wait();return a.exec();
}

运行

Result: 100

2.7.代码六:通过继承QThread的方式来运行一个纯函数,并将参数通过类的成员变量传递给这个函数

#include <QCoreApplication>
#include <QThread>
#include <QDebug>// 纯函数的声明
void pureFunction(int a, int b);// 继承自 QThread 的类
class WorkerThread : public QThread {public:// 构造函数WorkerThread(int a, int b, QObject *parent = nullptr) : QThread(parent), m_a(a), m_b(b) {}protected:// 重写 run 方法void run() override {// 在新线程中调用纯函数qDebug() << "线程开始执行";pureFunction(m_a, m_b);qDebug() << "线程执行完成";}private:int m_a, m_b;  // 成员变量,用于存储传递给纯函数的参数
};// 纯函数的实现
void pureFunction(int a, int b) {// 执行一些计算或处理int result = a + b;qDebug() << "纯函数执行结果:" << result;
}int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);// 创建 WorkerThread 对象,传递参数给纯函数WorkerThread thread(10, 20);// 启动线程thread.start();// 等待线程执行完成thread.wait();return a.exec();
}

运行

线程开始执行
纯函数执行结果: 30
线程执行完成

三.方法二:将任务放在QObject派生类中,并moveToThread()在QThread中运行这个QObject

3.1. 代码一:运行成员函数例程,让 Worker 类继承自 QObject,然后使用一个 QThread 实例来在另一个线程中运行这个 Worker 对象

// 包含必要的头文件
#include <QCoreApplication>
#include <QThread>
#include <QDebug>// Worker 类定义
class Worker : public QObject {Q_OBJECTpublic:Worker() {}virtual ~Worker() {}public slots:void process() {// 输出当前线程信息qDebug() << "Worker thread running in thread:" << QThread::currentThreadId();// 模拟耗时操作QThread::sleep(3);qDebug() << "Worker process completed.";emit finished();}signals:void finished();
};int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);// 创建线程对象QThread workerThread;Worker worker;// 将 worker 对象移动到新建的线程worker.moveToThread(&workerThread);// 连接信号和槽QObject::connect(&workerThread, &QThread::started, &worker, &Worker::process);QObject::connect(&worker, &Worker::finished, &workerThread, &QThread::quit);QObject::connect(&worker, &Worker::finished, &worker, &Worker::deleteLater);QObject::connect(&workerThread, &QThread::finished, &workerThread, &QThread::deleteLater);// 启动线程workerThread.start();// 运行事件循环int result = a.exec();// 等待线程结束workerThread.wait();return result;
}#include "main.moc"

运行

Worker thread running in thread: 0x7f1943a36700
Worker process completed.
double free or corruption (out)
15:43:36: The program has unexpectedly finished.

3.2. 代码二:运行成员函数例程,让 Worker 类继承自 QObject,然后使用一个 QThread 实例来在另一个线程中运行这个 Worker 对象

#include <QCoreApplication>
#include <QThread>
#include <QDebug>// Worker类,负责执行实际的计算
class Worker : public QObject {Q_OBJECTpublic:Worker(int a, int b) : m_a(a), m_b(b) {}public slots:void process() {int result = m_a + m_b;  // 简单的加法计算qDebug() << "计算结果:" << result;emit finished();}signals:void finished();private:int m_a;int m_b;
};int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);int value1 = 5, value2 = 3;Worker *worker = new Worker(value1, value2);QThread *thread = new QThread;// 将worker移动到线程worker->moveToThread(thread);// 连接信号和槽QObject::connect(thread, &QThread::started, worker, &Worker::process);QObject::connect(worker, &Worker::finished, thread, &QThread::quit);QObject::connect(worker, &Worker::finished, worker, &QObject::deleteLater);QObject::connect(thread, &QThread::finished, thread, &QObject::deleteLater);QObject::connect(thread, &QThread::finished, &a, &QCoreApplication::quit); // 确保应用退出// 启动线程thread->start();return a.exec();
}#include "main.moc"

运行

计算结果: 8

四.方法三:直接使用 QThread 和 Lambda

#include <QCoreApplication>
#include <QThread>
#include <QDebug>// 纯函数定义,用于计算两个整数的和
int add(int a, int b) {return a + b;
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 创建线程对象QThread* thread = new QThread;int x = 3, y = 4;// 将任务移至线程,使用lambda表达式QObject::connect(thread, &QThread::started, [=]() mutable {int result = add(x, y);qDebug() << "The sum of" << x << "and" << y << "is" << result;thread->quit();  // 线程任务完成,请求退出线程});// 清理线程资源QObject::connect(thread, &QThread::finished, thread, &QObject::deleteLater);// 启动线程thread->start();return a.exec();
}

运行

The sum of 3 and 4 is 7

五.方法四:QThread::create(Qt 5.10 及以上)

5.1.提要

  • 直接在 QThread类中没有提供直接创建并启动线程执行特定函数的方法(例如 QThread::create 是 C++11 后Qt 5.10 添加的功能,如果您使用的Qt版本较旧,这一功能可能不可用)

  • 在Qt中使用QThread来运行一个全局纯函数是一个比较通用的任务,在Qt中,通常通过继承QThread并重写run()方法来实现这一点,但使用QThread的能力来直接启动一个线程执行我们的函数。

5.1.1.QThread::create()代码一
#include <QCoreApplication>
#include <QThread>
#include <QDebug>void performCalculation(int a, int b) {int result = a + b;qDebug() << "计算结果:" << result;
}int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);QThread *thread = QThread::create(performCalculation, 5, 3);QObject::connect(thread, &QThread::finished, thread, &QObject::deleteLater);thread->start();return app.exec();
}
5.1.2.QThread::create()代码二
#include <QCoreApplication>
#include <QThread>
#include <QDebug>// 全局纯函数
void performCalculation(int a, int b) {int result = a + b;  // 简单的加法计算qDebug() << "计算结果:" << result;
}// 线程执行的函数
void runInThread(int a, int b) {// 创建线程对象QThread* thread = QThread::create([=](){performCalculation(a, b);});// 连接线程结束信号到删除槽,确保资源被清理QObject::connect(thread, &QThread::finished, thread, &QObject::deleteLater);// 启动线程thread->start();
}int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);// 在线程中执行全局函数runInThread(5, 3);return a.exec();
}

六.方法五:QtConcurrent::run()

#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include <QtConcurrent>// 全局纯函数
void performCalculation(int a, int b) {int result = a + b;  // 简单的加法计算qDebug() << "在线程" << QThread::currentThreadId() << "计算结果:" << result;
}int main(int argc, char *argv[]) {QCoreApplication app(argc, argv);// 使用QtConcurrent运行全局函数int value1 = 5, value2 = 3;QFuture<void> future = QtConcurrent::run(performCalculation, value1, value2);// 等待任务完成future.waitForFinished();return app.exec();
}

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

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

相关文章

ubuntu server 24.04 网络 SSH等基础配置

1 安装参考上一篇: VMware Workstation 虚拟机安装 ubuntu 24.04 server 详细教程 服务器安装图形化界面-CSDN博客 2 网络配置 #安装 sudo apt install net-tools#查看 ifconfig #修改网络配置 sudo vim /etc/netplan/50-cloud-init.yaml network:version: 2ethernets:en…

飞鸡:从小训练飞行的鸡能飞行吗?为什么野鸡能飞吗?是同一品种吗?今天自由思考

鸡的飞行能力在很大程度上受到其生理结构的限制。尽管鸡有翅膀&#xff0c;但与能够长时间飞行的鸟类相比&#xff0c;鸡的翅膀相对较小&#xff0c;且胸部肌肉较弱。再加上鸡的身体较重&#xff0c;这些因素共同限制了鸡的飞行能力。通常&#xff0c;鸡只能进行短暂的、低空的…

【wiki知识库】01.wiki知识库前后端项目搭建(SpringBoot+Vue3)

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 &#x1f33c;环境准备 想要搭建自己的wiki知识库&#xff0c;要提前搭建好自己的开发环境&#xff0c;后端我使用的是SpringBoot&#xff0c;前端使用的是Vue3&#xff0c;采用前后端分离的技术实现。同时使用了Mysql数…

单工无线发射接收系统

1 绪论 随着无线电技术的发展,通讯方式也从传统的有线通讯逐渐转向无线通讯。由于传统的有线传输系统有配线的问题,较不便利,而无线通讯具有成本廉价、建设工程周期短、适应性好、扩展性好、设备维护容易实现等特点,故未来通讯方式将向无线传输系统方向发展。同时,实现系…

mfc140.dll丢失原因和mfc140.dll丢失修复办法分享

mfc140.dll是与微软基础类库&#xff08;Microsoft Foundation Classes, MFC&#xff09;紧密相关的动态链接库&#xff08;DLL&#xff09;文件。MFC是微软为C开发者设计的一个应用程序框架&#xff0c;用于简化Windows应用程序的开发工作。以下是mfc140.dll文件的一些关键属性…

栈的实现(C语言)

文章目录 前言1.栈的概念及结构2.栈的实现3.具体操作3.1.初始化栈(StackInit)和销毁栈(StackDestory)3.2.入栈(StackPush)和出栈(StackPop)3.3.获得栈的个数(StackSize)、获得栈顶元素(StackTop)以及判空(StackEmpty) 前言 前段时间我们学习过了链表和顺序表等相关操作&#x…

go-zero 实战(4)

中间件 在 userapi 项目中引入中间件。go项目中的中间可以处理请求之前和之后的逻辑。 1. 在 userapi/internal目录先创建 middlewares目录&#xff0c;并创建 user.go文件 package middlewaresimport ("github.com/zeromicro/go-zero/core/logx""net/http&q…

经济寒冬下的黄金跳板:方案、活动、竞标一手掌握

推荐策划人必备的宝藏地产策划资源平台&#xff0c; 订阅浩叫&#xff1a;地产营销策划圈。这个平台简直是地产策划人的百宝箱&#xff0c;里面藏着无数的策划秘籍&#xff0c;等着你来挖掘。 这个平台就像是一个大型的方案库&#xff0c;里面收录了众多知名地产企业的内部资料…

leetcode:计数质数

class Solution { public:// 如果 x 是质数&#xff0c;那么大于 x 的 x 的倍数 2x,3x… 一定不是质数int countPrimes(int n) {vector<int> isPrime(n, 1);int ans 0;for (int i 2; i < n; i) {if (isPrime[i]) {ans 1;if ((long long)i * i < n) {for (int j …

leetcode-55 跳跃游戏

leetcode Problem: 55. 跳跃游戏 思路 假设我们是一个小人&#xff0c;从第一个下标开始&#xff0c;每次经过一个位置&#xff0c;我们就可以根据当前位置的数值nums[i]和位置下标i计算出该位置所能到达的后续位置的最大值rnums[i]i。而这个r之前的区域一定都是可以经过的。…

AI 谈“浔川AI翻译机”

在天工AI&#xff0c;天工AI在全网搜索“浔川AI翻译机”。 1 创作助手谈“浔川AI翻译机”&#xff1a; “浔川AI翻译机”是一个利用人工智能技术进行语言翻译的设备或应用程序。它可以将一种语言的文字或口语翻译成另一种语言&#xff0c;以实现不同语言之间的沟通和理解。浔…

Linux指令初识

ls:显示当前目录底下的指定文件或目录 ls -l更详细的信息 ls -a显示当前目录下的所有文件 命令中的选项可以一次传递多个 ,例如&#xff1a;ls -al 命令和选项有必须一个或多个空格 以.开头的文件&#xff0c;为隐藏文件ls -a可以看到,ls -l看不见 支持命令拼在一起&#…

牛客热题:滑动窗口的最大值

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题&#xff1a;滑动窗口的最大值题目链接方法一…

DNS服务的部署与配置(2)

1、dns的安装及开启 dnf install bind.x86_64 -y #安装 #Berkeley Internet Name Domain (BIND) systemctl enable --now named #启用dns服务&#xff0c;服务名称叫named firewall-cmd --permanent --add-servicedns #火墙设置 firewall-cmd --reload …

【手把手搓组件库】从零开始实现Element Plus--组件开发

从零开始实现Element Plus--组件开发 nvmnvm的作用&#xff1a;nvm的使用方法 需求分析提示词Kimi 生成产品需求文档kimi 生成测试用例 初始化 vitest完善 Button 组件1、定义 types.ts2、Button.vue 引入 types.ts3、添加Button样式点击事件 添加节流添加 Icon 集成 StoryBook…

C++第十九弹---string模拟实现(下)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1、修改操作 2、迭代器操作 3、字符串操作 4、非成员函数重载操作 总结 1、修改操作 1、string& operator (const char* s); //尾部插入…

【Text2SQL 论文】SeaD:使用 Schema-aware 去噪训练的 end2end 的 Text2SQL

论文&#xff1a;SeaD: End-to-end Text-to-SQL Generation with Schema-aware Denoising ⭐⭐ NAACL 2022, arXiv:2105.07911 本论文提出 SeaD 模型&#xff0c;使用 schema-aware 的去噪方法来训练一个 end2end、seq2seq 的 Transformer 模型来实现 Text2SQL。 一、论文速读…

C++系列-static成员

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 概念 声明为static的类成员称为类的静态成员&#xff0c;用static修饰的成员变量&#xff0c;称之为静态成员变量&#xff0c;用static修饰的成员函数&#xff0c;称之为静态成…

stm32学习-流水灯

接线 注意&#xff1a;LED灯长一点的引脚是正极。 配置GPIO 1.使用RCC开启GPIO时钟 void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState); void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState); void RCC_APB1Perip…

【Qt 学习笔记】Qt窗口 | 菜单栏 | QMenuBar的使用及说明

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt窗口 | 菜单栏 | QMenuBar的使用及说明 文章编号&#xff1a;Qt 学习…