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

【QT】编写第一个 QT 程序 对象树 Qt 编程事项 内存泄露问题

目录

1. 编写第一个 QT 程序

1.1 使用 标签 实现  

1.2 纯代码形式实现

1.3 使用 按钮 实现 

1.3.1 图形化界面实现 

1.3.2 纯代码形式实现

1.4 使用 编辑框 实现

1.4.1 图形化界面实现

 1.4.2 纯代码形式实现 

1.4.3 内存泄露 

2. 认识对象模型(对象树)

2.1 什么是对象树

2.2 验证对象树

3. 解决编码问题

4. Qt 编程注意事项

4.1 Qt 中的命名事项

4.2 Qt Creator 中的快捷键

4.3 使用帮助文档

5. 小结


1. 编写第一个 QT 程序

1.1 使用 标签 实现  

1.创建好一个项目后,我们可以点击 widget.ui 进入图形化界面设计,可以直接通过拖拽的方式进行添加

2.拖拽 "标签" 至 UI 设计界面中,并双击修改标签内容

3. 此时ui界面就会生成对应的 XML 格式代码,这个时候qmake就会根据这个XML代码生成对应的C++代码,我们也可以在同目录下找到这个C++代码

1.2 纯代码形式实现

我们点击 widget.cpp 里面,会有一个 widget 的构造函数和析构函数,我们一般使用代码进行编辑界面的时候,一般都是在 widget 的构造函数中实现,因为在  main 函数中调用了 widget 类之后就直接 show了,所以卸载构造函数中的时候,一旦执行到了 show 就一定可以显示出设计的界面

#include "widget.h" // 创建生成时的文件
#include "ui_widget.h"
#include <QLabel>  // 包含标签的头文件Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this); // 将form file生成的界面和我们当前的widget进行关联起来// 创建对象的两种方法// QLabel label; // 在栈上创建QLabel* label = new QLabel(this); // 在堆上创建,推荐这种方法,还要传递 一个 this,给当前这个 lable 对象指定 父对象// 1. 设置标签内容label->setText((QString)("显式 Hello world"));label->setText("隐式 Hello World"); // QString 也提供了 C 风格字符串作为参数的构造函数来不显示构造 QString// 注意:由于QString 对应的头文件,已经被很多 Qt 内置的其他类给间接包含了.因此一般不需要显式包含 QString 头文件// 这里虽然有两次 setText,但是下面内容会覆盖上面内容// 2. 设置窗口大小setFixedSize(500, 400);// 3. 设置字体大小QFont font("楷体", 16);label->setFont(font);// 4. 设置标签内容显式位置label->move(200, 150);// 5. 设计标签字体颜色label->setStyleSheet("color:blue");
}Widget::~Widget()
{delete ui;
}

void setText(const QString &);

这里我们会发下使用字符串的时候并不是我们 C++ 使用的标准库中的 string,而是 Qt 自己包装好的字符串 QString 。这个其实也是历史原因,Qt 诞生于1991年,那个时候 C++ 还没有定标准,而 Qt 为了更好的开发就自己包装了一些容器。但是我们也还是可以使用 C++ 的标准库中的容器来使用

1.3 使用 按钮 实现 

1.3.1 图形化界面实现 

1. 双击:"widget.ui" 文件

2. 拖拽控件至 ui 界面窗口并修改内容

  • 虽然那里有好几个按钮,但是我们这里用 Push Button(普通按钮)

3. 构建并运行,效果如下所示

  • 这里的按钮的确可以点击,但是却没有任何反应,这个就设计到我们后面学的信号槽知识,后面会说的

  • QT 的信号槽机制:本质上就是给按钮的点击操作,关联上一个处理函数,当用户点击的时候,就会执行这个处理函数

这里我们的按钮没有任何功能,假如我们要实现一定的功能,那该怎么做呢?

打开 widget.ui 文件,查看设计的右下角,则有

如下代码:

widget.hpp

#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);void handleClick();~Widget();private:Ui::Widget *ui;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 按钮的点击操作 -- 信号槽// 在 Linux 网络编程那也有个connect 函数,那里用来给 TCP socket 建立连接的,写 TCP 客户端的时候,就需要先建立连接才能读写数据// ui->pushButton:谁发出的信号// &QPushButton::clicked:发出了啥信号,点击按钮的时候自动触发该信号// this: 谁来处理这个信号// Widget::handle:具体怎么处理connect(ui->pushButton, &QPushButton::clicked, this, &Widget::handleClick);  // 访问到 form file(ui 文件)中创建的控件}Widget::~Widget()
{delete ui;
}void Widget::handleClick()
{if(ui->pushButton->text() == "Hello World"){ui->pushButton->setText("Hello IsLand");}else{ui->pushButton->setText("Hello World");}
}

返回上级目录查看 ui_widget.h 文件

因此我们也可以把 PushButton 改成其他的,如下:

再次查看 ui_widget.h 文件,如下:

结论:在 objectName 中,设置成什么值,生成的变量名就叫啥名字就可以根据这个名字来获取到对应的控件的变量了

1.3.2 纯代码形式实现

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QPushButton>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);void handleClick();~Widget();private:Ui::Widget *ui;QPushButton* myButton;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);myButton = new QPushButton(this);myButton->setText("Hello World");connect(myButton, &QPushButton::clicked, this, &Widget::handleClick);  // 访问到 form file(ui 文件)中创建的控件
}Widget::~Widget()
{delete ui;
}void Widget::handleClick()
{if(myButton->text() == QString("Hello World")){myButton->setText("Hello IsLand");}else{myButton->setText("Hello World");}
}

实现效果如下图:

两个版本比较:

  • 图形化实现:此时按钮对象不需要咱们自己 newnew 对象的操作已经是被 Qt 自动生成了而且这个按钮对象,已经作为 ui 对象里的一个成员变量了,也无需作为 Widget 的成员

  • 纯代码实现:按钮对象是咱们自己 new 的,为了保证其他函数中能够访问到这个变量,就需要把按钮对象,设定为 Widget 类的成员变量

实际开发中,是通过代码的方式构造界面为主,还是通过图形化界面的方式构造界面为主??

  • 这两种都很主要,难分主次!!

  • 如果你当前程序界面,界面内容是比较固定的,此时就会以 图形化 的方式来构造界面

  • 但是如果你的程序界面,经常要动态变化,此时就会以 代码 的方式来构造界面

  • 反正这两种方式哪种方便用哪个,也可以配合来使用

1.4 使用 编辑框 实现

  • 单行编辑框: QLineEdit
  • 多行编辑框: QTextEdit
1.4.1 图形化界面实现

  • 当然输出的文本框,我们也可以在输出里面进行修改啥的,但是不会影响代码里面的文本数据

 1.4.2 纯代码形式实现 

1.4.3 内存泄露 

在上面的代码实现中,我们使用 new 创建了对象,在栈上开辟了一块空间之后,但是我们没有使用delete进行释放控件,这样不就会导致内存泄漏啊

  • 其实上述代码在 Qt 不会产生内存泄露, label  对象会在合适的时候被析构释放,之所以能够把对象释放掉,主要是因为把这个对象挂到了 对象树 上 

  • 前端开发(网页开发)也涉及到 类似的 对象树 (DOM),本质上也是一个树形结构(N 又树),通过树形结构把界面上的各种元素组织起来

  • Qt 中也是类似,也是搞了一个对象树,也是 N 又树,把界面上的各种元素组织起来了

  • 用对象树把这些内容组织起来,最主要的目的:就是为了能够在合适的时机(窗口关闭和销毁),把这些对象统一进行释放。通过这个树形结构,就把界面上要显示的这些控件对象都组织起来了。
  • 这里的树上的这些对象,统一销毁是最好不过的,如果某个对象提前销毁,此时就会导致对应的控件就在界面上不存在了。

2. 认识对象模型(对象树)

2.1 什么是对象树

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

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

  • 当创建一个 QObject 对象时,会看到 QObject 的构造函数接收一个 QObject 指针作为参数,这个参数就是 parent,也就是父对象指针。

  • 这相当于,在创建 QObject 对象时,可以提供一个其父对象,我们创建的这个 QObject 对象会自动添加到其父对象的 children()列表。

  • 当父对象析构的时候,这个列表中的所有对象也会被析构。(注意,这里的父对象并不是继承意义上的父类!)

这种机制在 GUI程序设计中相当有用。例如,一个按钮有一个 QShortcut(快捷键)对象作为其子对象。当删除按钮的时候,这个快捷键理应被删除。这是合理的。

  • Qwidget 是能够在屏幕上显示的一切组件的父类。
  • Qwidget 继承自 QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的-个子组件。因此,它会显示在父组件的坐标系统中,被父组件的边界剪裁。例如,当用户关闭一个对话框的时候,应用程序将其删除,那么,我们希望属于这个对话框的按钮、图标等应该(-起被删除。事实就是如此,因为这些都是对话框的子组件。
  • 当然,我们也可以自己删除子对象,它们会自动从其父对象列表中删除。比如,当我们删除了个工具栏时,其所在的主窗口会自动将该工具栏从其子对象列表中删除,并且自动调整屏幕显示。

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

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

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

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

{QWidget window;QLabel label("hello", &window); // 指定父类是widow
}

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

  • 但是一旦我们的代码稍微修改一点就会出错
{QLabel label("hello"); // 指定父类是widowQWidget window;label.setParent(&window);
}

情况又有所不同,析构顺序就有了问题。我们看到,在上面的代码中,作为父对象的 window 会首先被析构,因为它是最后一个创建的对象。在析构过程中,它会调用子对象列表中每一个对象的析构函数,也就是说,label此时就被析构了。然后,代码继续执行,在 window 析构之后,label也会被析构,因为 label也是一个局部变量,在超出作用域的时候当然也需要析构。但是,这时候已经是第二次调用 label的析构函数了,C++不允许调用两次析构函数,因此,程序崩溃了。

由此我们看到,Qt 的对象树机制虽然在一定程度上解决了内存问题,但是也引入了一些值得注意的事情。这些细节在今后的开发过程中很可能时不时跳出来烦扰一下,所以,我们最好从开始就养成良好习惯,即 在 Qt 中,尽量将其开辟在堆上,并指定好其 parent 父类对象

比如:

  • 如果我们把最初的代码改成在栈上开辟的话我们运行程序会发现什么都没有

Qt 对象树如下:

2.2 验证对象树

首先我们自定义一个label类,并在析构部分打上日志,如下步骤:

1. 选中工程名,鼠标右键------->"add new..."(或 "添加新文件" )

结果图如下: 

  • 上面 Qt Creator 是帮我们生成了一些代码,但是没完全生成,头文件没有给我们主动包含,上面的头文件也是我自己手动包含的 
  • 此时我们可以按F4来进行 .h文件 和 .cpp文件 来回切换

此时我们的 mylabel.cpp 中就是

#include "mylabel.h"
#include <iostream>MyLabel::MyLabel(QWidget* parent) : QLabel(parent)
{
}MyLabel::~MyLabel()
{std::cout << "MyLabel 被销毁" << std::endl;
}

midget.cpp 中的代码就是

#include "widget.h"
#include "ui_widget.h"
#include "mylabel.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this); // 将form file生成的界面和我们当前的widget进行关联起来// 使用自己定义的 MyLabel 代替原来的 QLabel,所谓的 “继承” 本质上是扩展,保持原有功能不变的基础上// 给对象扩展出一个析构函数,通过这个析构函数,打印一个自定义日志,方便观察程序运行结果MyLabel *label = new MyLabel(this);label->setText("Hello World");}Widget::~Widget()
{delete ui;
}
  • 此时我们运行代码,就可以看到窗口上有 Hello World 的字样,只要我们关闭窗口,就会输出我们的日志

这里也是验证了对象树自动释放对象的能力

  • 这里日志是有的,说明析构函数是执行了,虽然没有 手动 delete,但是由于把 MyLabel 挂到了对象树上,此时窗口被销毁的时候,就会自动销毁对象树中的所有对象!!所以MyLabel 的析构是执行到了

但是这里似乎出现了乱码的情况

  • 乱码问题出现的原因有且仅有一个 编码方式不匹配(不仅仅局限于 C++)
  • 比如字符串本身是 utf8 编码的,但是终端(控制台)是按照 gbk 的方式来解析显示的,就会出现乱码(相当于拿着 utf8 的数值 去查询 gbk 的 码表)

utf8 和 gbk 

目前,表示汉字字符集, 主要是两种方式

  1. GBK(中国大陆) 使用 2 个字节表示一个汉字!Windows 简体中文版,默认的字符集就是 GBK
  2. UTF-8 / utf8 变长编码,表示一个符号,使用的字节数有变化,2-4但是在 utf8 中。一个汉字一般是 3 个字节
  3. Linux 默认就是 utf8

3. 解决编码问题

我们用文本文件打开 mylabel.cpp 文件,可以看到这个文件的编码方式

可看到这个文件的编码方式是 utf8,但是  Qt 的这个终端的编码方式肯定不是 utf8 ,但是Qt不支持修改编码方式,所以这里我们就需要借助 Qt 自己提供的打印日志的功能 qDebug,或者使用 QString 来处理编码方式。

#include "mylabel.h"
#include <iostream>#include <QtDebug> // 头文件MyLabel::MyLabel(QWidget* parent) : QLabel(parent)
{}MyLabel::~MyLabel()
{// std::cout << "MyLabel 被销毁" << std::endl;qDebug() << "MyLabel 被销毁"; // qDebug 这个宏封装了 QDebug 对象,使用 qDebug 相当于使用 cout
}
#define qDebug QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).debug

此时中文就不会出现乱码情况,如下: 

  • 后续在 Qt 中,如果想通过打印日志的方式,输出一些调试信息,都优先使用 qDebug。虽然使用 cout 也行,但是 cout 对于编码的处理不太好,在windows 上容易出现乱码(如果是 Linux 使用 Qt Creator, 一般就没事了,Linux 默认的编码一般都是 utf8)

  • 使用 qDebug, 还有一个好处:打印的调试日志是可以统一进行关闭的!!

  • 输出的日志,是开发阶段、调试程序的时候使用的。如果你的程序发布给用户,不希望用户看到这些日志的!!

  • qDebug 可以通过编译开关,来实现一键式关闭

之前调试程序, 都是用调试器.VS/gdb,这里为啥要打印日志调试呢??

  • 调试器很多时候是有局限性的,是无法使用的,
  • 假设当前 bug 是一个概率性的 bug。出现的概率是 1% 甚至更小要想调试,无法使用调试器了
  • 使用 日志  就可以很好的解决这种问题
  • 无论是哪种方式本质上都是观察程序执行的中间过程和中间结果~

4. Qt 编程注意事项

4.1 Qt 中的命名事项

  • 类名:首字母大写,单词和单词之间首字母大写;

  • 函数名及变量名:首字母小写,单词和单词之间首字母大写

  • 起的名字要有描述性,不要使用 abc, xyz 这种比较无规律的名字来描述

  • 如果名字比较长,由多个单词构成的,就需要使用适当的方式来进行区分不同单词

  • 一般可以采用 蛇形命名法 或者 驼峰命名法

4.2 Qt Creator 中的快捷键

其里面内置 Vim 插件,因此我们也可以按照使用 Vim 操作来使用

  • 注释:ctrl+/

  • 运行:ctrl+R

  • 编译:ctrl+B

  • 字体缩放:ctrl+鼠标滑轮

  • 查找:ctrl+F

  • 整行移动:ctrl+shift+↑/↓

  • 帮助文档:F1

  • 自动对齐:ctrl+i

  • 同名之间的.h和.cpp 的切换:F4

  • 生成函数声明的对应定义:alt+enter

  • 跳转到控件定义: 鼠标左键 + ctrl,返回就是:alt + <-

4.3 使用帮助文档

打开帮助文档有三种方式,实际编程中使用哪种都可以

  1. 光标放到要查询的类名/方法名上,直接按 F1

  2. Qt Creator 左侧边栏中直接用鼠标单击"帮助"按钮

点击 "帮助" 之后,出现如下图:

3、找到 Qt Creator 的安装路径,在 "bin" 文件夹下找到 assistant.exe,双击打开

使用示例

  1. 新建项目,在新建的项目中使用 Qt 中的"QpushButton" 控件。

  2. 打开帮助手册,在"索引"里面输入"QpushButton":

注意:一定不要使用中文文档!!!

  • 阅读英文文档是每个程序员必备的专业技能,必须要练,不能退缩

  • Qt的文档从通俗易懂的角度来说,是技术类文档中非常出类拔萃的,只要大家稍微有点耐心,基本都能读懂个八九不十

5. 小结

  • 认识 QLabel 类,能够在界面上显示字符串。通过 setText 来设置的,参数 QString(Qt 中把 C++ 里的很多容器类,进行了重新封装,历史原因)

  • 内存泄露/文件资源泄露

  • 对象树Qt 中通过对象树,来统一的释放界面的控件对象,Qt 还是推荐使用 new 的方式在堆上创建对象,通过对象树,统一释放对象创建对象的时候,在构造函数中,指定父对象(此时才会挂到对象树上),如果你的对象没有挂到对象树上,就必须要记得手动释放!!

  • 通过继承自 Qt 内置的类,就可以达到对现有控件进行功能扩展效果Qt 内置的 QLabel,没法看到销毁过程的。为了看清楚,就创建类 MyLabel, 继承自 QLabel 重写析构函数。在析构函数中加上日志,直观的观察到对象释放的过程了,也可以重写控件中的任何功能。不仅仅是析构函数, 达到功能扩展目的

  • 乱码问题 和 字符集~ MySQL(很多地方都涉及到)

  • 如何在 Qt 中打印日志,作为调试信息使用 cout 固然可以, 但是并不是上策(字符编码处理的不好,也不方便统一进行关闭)Qt 中推荐使用 qDebug() 完成日志的打印

相关文章:

【QT】编写第一个 QT 程序 对象树 Qt 编程事项 内存泄露问题

目录 1. 编写第一个 QT 程序 1.1 使用 标签 实现 1.2 纯代码形式实现 1.3 使用 按钮 实现 1.3.1 图形化界面实现 1.3.2 纯代码形式实现 1.4 使用 编辑框 实现 1.4.1 图形化界面实现 1.4.2 纯代码形式实现 1.4.3 内存泄露 2. 认识对象模型&#xff08;对象树&…...

92.一个简单的输入与显示示例 Maui例子 C#例子

一、关于项目命名的注意事项 在开发.NET MAUI项目时&#xff0c;项目命名是一个不可忽视的细节。如果你习惯了在C#控制台或WPF项目中使用中文项目名称&#xff0c;那么在.NET MAUI中&#xff0c;你可能会遇到一些问题。我之前就因为使用中文项目名称而导致项目无法直接运行&am…...

SpringAI实现AI应用-搭建知识库

SpringAI实战链接 1.SpringAl实现AI应用-快速搭建-CSDN博客 2.SpringAI实现AI应用-搭建知识库-CSDN博客 概述 想要使用SpringAI搭建知识库&#xff0c;就要使用SpringAI中的TikaDocumentReader&#xff0c;它属于ETL&#xff08;提取、转换、加载&#xff09;框架中的提取&…...

大连理工大学选修课——机器学习笔记(4):NBM的原理及应用

NBM的原理及应用 贝叶斯决策及相关 贝叶斯决策 对于给定数据集 X [ X 1 , X 2 , ⋯ , X d ] T X[X_1,X_2,\cdots,X_d]^T X[X1​,X2​,⋯,Xd​]TK个类 C i , i 1 , ⋯ , K C_i,i1,\cdots,K Ci​,i1,⋯,K, 满足 P ( C i ) > 0 a n d ∑ P ( C i ) 1 P(C_i)>0\ and\ …...

SQL Server 数据库重命名

通过将 SQL Server 数据库置于单用户模式&#xff0c;对其重命名 使用下列步骤在 SSMS 中使用 T-SQL 重命名 SQL Server 数据库。 1.为实例连接到 master 数据库。 2.打开一个查询窗口。 3.将以下示例复制并粘贴到查询窗口中&#xff0c;然后选择“执行”。 此示例将 MyTes…...

5W1H分析法——AI与思维模型【86】

一、定义 5W1H分析法思维模型是一种通过对问题或事件从原因&#xff08;Why&#xff09;、对象&#xff08;What&#xff09;、地点&#xff08;Where&#xff09;、时间&#xff08;When&#xff09;、人员&#xff08;Who&#xff09;和方法&#xff08;How&#xff09;六个…...

【closerAI ComfyUI】开源社区炸锅!comfyUI原生支持Step1X-Edit 图像编辑!离简单免费高效又进一步

添加图片注释,不超过 140 字(可选) 更多AI前沿科技资讯,请关注我们: closerAI-一个深入探索前沿人工智能与AIGC领域的资讯平台 【closerAI ComfyUI】开源社区炸锅!comfyUI原生支持Step1X-Edit 图像编辑!离简单免费高效又进一步! 大家好,我是Jimmy。前面有介绍了阶跃…...

spring中关键字Assert和jdk的assert关键字

你提出的问题非常关键&#xff0c;涉及到 Java 中两种不同的 assert 用法&#xff1a; ✅ 一、你提到的两种 assert 类型 示例 来源 特点 JDK 自带的 assert 关键字 assert str ! null; Java 原生语言特性&#xff08;JDK 1.4&#xff09; 可开关控制&#…...

git分支分叉强制更改为线性

git分支分叉更改为线性 远端分支情况 本地分支情况 在执行 git pull origin main 时遇到了一个提示&#xff0c;说明本地分支和远程分支发生了分歧&#xff08;divergent branches&#xff09;。 这通常是因为远程分支上有新的提交&#xff0c;而本地分支也有未推送的提交&a…...

从实列中学习linux shell6: 写一个 shell 脚本 过滤 恶意ip 攻击

下面是检测和过滤恶意IP攻击的Shell脚本&#xff0c;包含自动分析日志、封锁IP、白名单管理等功能&#xff1a; 第一步&#xff1a;过滤脚本 #!/bin/bash# 配置区域&#xff08;根据需求修改&#xff09; LOG_FILES(/var/log/auth.log /var/log/nginx/access.log) # 监控的日…...

代码随想录打卡|Day31动态规划(最后一块石头的重量2、目标和、一和零)

动态规划Part 04 最后一块石头的重量 II 力扣题目链接 代码随想录链接 视频讲解链接 题目描述&#xff1a; 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉…...

一区思路!挑战5天一篇NHANES预测模型 DAY1-5

挑战5天一篇预测模型NHANES Day1! 近期美国关闭seer数据库的信息在互联网上广泛传播&#xff0c;大家都在担心数据库挖掘是否还能做。这个问题其实是有答案的&#xff0c;数据库挖掘肯定能做&#xff0c;做没被关的数据库即可&#xff0c;同时留意一些国产数据库&#xff5e;…...

Stack--Queue 栈和队列

一、Stack--栈 1.1 什么是栈&#xff1f; 堆栈是一种容器适配器&#xff0c;专门设计用于在 LIFO 上下文&#xff08;后进先出&#xff09;中运行&#xff0c;其中元素仅从容器的一端插入和提取。 第一个模版参数T&#xff1a;元素的类型&#xff1b;第二个模版参数Container…...

Redis热key大key详解

不要阻挡我走向成功&#xff0c;勇者配享所有&#xff0c;感想敢干 hotkey热key 大量请求可能会使redis节点流量不均匀&#xff0c;进而导致宕机&#xff0c;继而打到数据库崩溃&#xff1b;因此需要对热key优化 引发问题&#xff1a; 分片服务瘫痪可能打到数据库&#xff0…...

软件架构选型之“如何选”

本文提出的多维度评估框架旨在建立客观、全面的架构选型方法论&#xff0c;帮助团队做出更科学的架构决策&#xff0c;通过业务需求、技术约束、组织能力和演进策略四个核心维度建立量化评估模型。该框架旨在解决移动应用架构决策中的主观性和片面性问题&#xff0c;提供系统化…...

C语言写文件模式错误

“w” 和“wb”区别 出错实例 图像.raw文件输出时&#xff0c;采用“w”模式打开写文件&#xff0c;会将值为0A (即\n的ASCII值)&#xff0c;前自动添加0D(即\r的ASCII值)&#xff0c;如下图所示...

2025最新福昕PDF编辑器,PDF万能处理工具

软件介绍 Foxit PDF Editor Pro 2025 中文特别版&#xff08;以前称为 Foxit PhantomPDF Business&#xff09;是一款专为满足各种办公需求而设计的业务就绪的PDF工具包。 软件特点 1. 强大的PDF编辑能力 创建新文档&#xff1a;用户可以从无到有地构建PDF文档&#xff0c;添…...

Android 动态权限申请

ContextCompat.checkSelfPermission 检查应用是否具有某个危险权限。如果应用具有此权限&#xff0c;方法将返回PackageManager.PERMISSION_GRANTED&#xff0c;并且应用可以继续操作。如果应用不具有此权限&#xff0c;方法将返回PackageManager.PERMISSION_DENIED&#xff0c…...

【模型量化】量化基础

目录 一、认识量化 二、量化基础原理 2.1 对称量化和非对称量化 2.1.1 对称量化 2.1.2 非对称量化 2.1.3 量化后的矩阵乘 2.2 神经网络量化 2.2.1 动态量化 2.2.2 静态量化 2.3 量化感知训练 一、认识量化 量化的主要目的是节约显存、提高计算效率以及加快通信 dee…...

智能 + 安全:婴幼儿托育管理实训基地标准化建设方案

婴幼儿托育服务与管理实训基地智能安全的开发&#xff0c;需以“岗位能力-职业标准-行业需求”为核心逻辑&#xff0c;构建“需求分析-课程设计-教学实施-效果评估”全闭环体系。结合托育行业难点、技术赋能手段及职业能力要求&#xff0c;呈现课程开发全流程&#xff0c;重点突…...

AI重构家居营销新范式:DeepSeek如何破解行业流量与转化困局?

1. 流量下滑、成本攀升、内容同质化&#xff1a;家居行业亟需一场“效率革命” 中国家居行业正经历一场深刻的转型阵痛。线下门店客流量持续萎缩&#xff0c;线上获客成本攀升至临界点&#xff0c;传统营销模式陷入“高投入、低转化”的泥潭&#xff1b;智能家居产品快速迭代&…...

机器学习实操 第一部分 机器学习基础 第7章 集成学习与随机森林

机器学习实操 第一部分 机器学习基础 第7章 集成学习与随机森林 内容概要 第7章深入探讨了集成学习方法&#xff0c;这是一种结合多个预测模型&#xff08;如分类器或回归器&#xff09;以提高预测性能的技术。这些方法通过利用群体的智慧&#xff0c;可以比单个模型获得更好…...

如何用GPU Instancing来优化树木草石重复模型

1&#xff09;如何用GPU Instancing来优化树木草石重复模型 2&#xff09;Unity ASTC压缩后的纹理在部分安卓机型上不显示 3&#xff09;现在大部分项目的竖版UI设计分辨率是多少 4&#xff09;Android上拖拽物体不实时跟随手指的问题 这是第430篇UWA技术知识分享的推送&#x…...

Windows服务器部署全攻略:Flask+Vue+MySQL跨平台项目实战(pymysql版)

当你的后端(Flask+pymysql,Windows开发)与前端(Vue,Mac开发)需要统一部署到Windows服务器时,通过「IIS反向代理+原生组件适配」方案可实现稳定交互。以下是针对Windows环境的专属部署指南,解决路径适配、服务启动等核心问题。 一、Windows服务器环境准备(必做!) 1…...

自动驾驶-一位从业两年的独特视角

时间简介 2023.03 作为一名大三学生&#xff0c;加入到某量产车企&#xff0c;从事地图匹配研发 2023.07 地图匹配项目交付&#xff0c;参与离线云端建图研发 2023.10 拿到24届校招offer 2024.07 正式入职 2025.01 离线云端建图稳定&#xff0c;开始接触在线车端融图研发 自动…...

Vue 3 单文件组件中 VCA 语法糖及核心特性详解

在 Vue.js 的开发世界里&#xff0c;单文件组件&#xff08;Single File Components&#xff0c;简称 SFC&#xff09;是构建复杂应用的基石。它将 HTML、CSS 和 JavaScript 代码封装在一个.vue文件中&#xff0c;极大地提高了代码的可维护性和复用性。 本文将深入探讨单文件组…...

iVX:数字化转型全场景技术革新与生态构建实践

在数字经济蓬勃发展的当下&#xff0c;企业数字化转型需求日益迫切。iVX 凭借其独特的技术架构与创新解决方案&#xff0c;深度渗透工业互联网、元宇宙、智慧城市等领域&#xff0c;成为推动全场景数字化转型的重要力量。本文将重新梳理 iVX 的技术应用与生态价值&#xff0c;以…...

车辆检测新突破:VFM-Det 如何用大模型提升识别精度

目录 ​编辑 一、摘要 二、引言 三、相关工作 四、Coovally AI模型训练与应用平台 五、方法 概述 综述&#xff1a;基于区域建议的检测 基于VehicleMAE的感知器 六、实验分析 数据集与评估指标 实现细节 属性预测模块预训练 与SOTA检测器的对比实验 消融实验 V…...

可视化图解算法:判断是否完全二叉树

1. 题目 描述 给定一个二叉树&#xff0c;确定他是否是一个完全二叉树。 完全二叉树的定义&#xff1a;若二叉树的深度为 h&#xff0c;除第 h 层外&#xff0c;其它各层的结点数都达到最大个数&#xff0c;第 h 层所有的叶子结点都连续集中在最左边&#xff0c;这就是完全二…...

对于C++中的STL,push_back()和emplace_back()有什么区别?

1.push_back()&#xff1a; 语法为&#xff1a;container.push_back()&#xff0c;接收一个值或一个对象的移动/复制副本&#xff1b; 在将对象添加或移动到容器的末尾前&#xff0c;需要先调用构造函数实例化对象&#xff0c;然后再执行移动或复制操作。 2.emplace_back()&a…...

小程序中的页面跳转

小程序中的页面跳转 在之前网页的学习中&#xff0c;我们往往采用超链接&#xff0c;或者定义方法、函数等方式来实现页面的跳转&#xff0c;但是微信小程序中没有超链接&#xff0c;那我们该如何实现呢&#xff1f;微信小程序的页面跳转包括两个&#xff0c;一个是tabBar页面…...

分享一款免费的AI IDE Trae,全新支持DeepSeek R1/V3、豆包大模型1.5自由切换,更可自定义专属AI模型

分享一款免费的AI IDE Trae&#xff0c;全新支持DeepSeek R1/V3、豆包大模型1.5自由切换,更可自定义专属AI模型,加入我的邀请一起拿好礼,转发给技术搭子还有机会赢取华为MatePad Air、雷蛇机械键盘、热门会员卡等丰厚奖品&#xff0c;即刻体验>>: https://juejin.cn/loy…...

美团优选小程序 mtgsig 分析 mtgsig1.2

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 逆向过程 部分python代码 openId a…...

Java中的多态与继承

Java中的多态与继承 开始学习Java中的多态及如何在多态方法调用中进行方法调用 多态——即对象根据其类型执行特定操作的能力——是Java代码灵活性的核心。四人组&#xff08;Gang Of Four&#xff09;创建的许多设计模式都依赖于某种形式的多态&#xff0c;包括命令模式。本文…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(12): ておき ます

日语学习-日语知识点小记-构建基础-JLPT-N4阶段&#xff08;12&#xff09;&#xff1a; ておき ます。 1、前言&#xff08;1&#xff09;情况说明&#xff08;2&#xff09;工程师的信仰 2、知识点&#xff08;1&#xff09;&#xff5e;ておき ます。&#xff08;2&#x…...

MicroPython for esp32s3开发HX711称重模块指南

一、HX711模块基本介绍 一&#xff09;、核心功能 ‌24位高精度ADC‌ 专为称重传感器设计的模数转换芯片&#xff0c;支持20mV或40mV满幅差分输入内置128/64倍可编程增益放大器&#xff08;通道A&#xff09;及固定32倍增益&#xff08;通道B&#xff09; ‌集成化设计‌ 集成…...

智能机器人在物流行业的应用:效率提升与未来展望

随着全球电子商务的蓬勃发展&#xff0c;物流行业正面临着前所未有的挑战和机遇。传统的物流模式已经难以满足日益增长的市场需求&#xff0c;尤其是在效率、成本控制和精准配送方面。智能机器人技术的出现&#xff0c;为物流行业的转型升级提供了强大的动力。本文将探讨智能机…...

MiWi|Microchip开发的专有无线通信协议,适用于低功耗、短距离的无线个人局域网【无线通信小百科】

1、什么是MiWi MiWi&#xff08;Microchip Wireless&#xff09;是一种由 Microchip 公司开发的专有无线通信协议。 它基于 IEEE 802.15.4 标准&#xff0c;适用于低功耗、短距离的无线个人局域网&#xff08;WPAN&#xff0c;Wireless Personal Area Network&#xff09;。 M…...

分布式事务,事务失效,TC事务协调者

1. 概述 本方案书旨在解决分布式系统中事务一致性问题&#xff0c;重点阐述全局事务标识&#xff08;XID&#xff09;的传递与存储机制、事务协调者&#xff08;TC&#xff09;的设计与部署&#xff0c;以及分布式事务失效场景的应对策略。基于业界成熟框架&#xff08;如Seat…...

ESP32开发-作为TCP客户端发送数据到网络调试助手

​​代码&#xff08;作为TCP客户端&#xff09;​​ #include <SPI.h> #include <EthernetENC.h> // 使用EthernetENC库// 网络配置 byte mac[] {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // MAC地址 IPAddress ip(192, 168, 1, 100); // ESP32的IP IPAddr…...

halcon打开图形窗口

1、dev_open_window 参数如下&#xff1a; 1&#xff09;Row(输入参数) y方向上&#xff0c;图形窗口距离左上角顶端的像素个数 2&#xff09;Column(输入参数) x方向上&#xff0c;距离左上角左边的像素个数 3&#xff09;Width(输入参数) 图形窗口宽度 4&#xff09;He…...

LVGL -按键介绍 下

4 图标 4.1 内置图标 LVGL 提供了一个很方便的 图标字体 系统&#xff0c;它使用了 lv_label 来显示文本或图标。你可以选择 Font Awesome 或其他图标字体&#xff0c;并将其直接嵌入应用中。LVGL 内建图标字体&#xff08;如 LV_SYMBOL_*&#xff09;是可以改变大小的。通过…...

【默子速报】DeepSeek新模型 Prover-V2 报告解读

炸裂&#xff0c;太炸裂了&#xff0c;五一不放假是吧&#xff1f;&#xff01; 默子加班加点的肝解读&#xff01; 首先是&#xff0c;Deepseek今天下午显示毫无预兆的在HF上发布了最新的Prover-V2参数 直接让一群人瞬间热血沸腾&#xff0c;想要看看Deepseek又干了什么大事。…...

冰冰一号教程网--介绍采用vuepress搭建个人博客

文章说明 采用vuepress可以快速搭建个人网站&#xff0c;风格统一&#xff1b;采用GPT可以将博文转化为个人博客网站 冰冰一号教程网 访问地址 目前只支持到 2025年05月1号 22点 教程包括主流编程语言&#xff1a;Java、JavaScript、python、C语言、C、C# 教程讲义由GPT生成&am…...

借助电商 API 接口实现电商平台商品数据分析的详细步骤分享

在数字化商业浪潮中&#xff0c;电商平台积累了海量数据。如何从这些数据中挖掘有价值的信息&#xff0c;成为电商企业提升竞争力的关键。电商 API 接口在这一过程中发挥着核心作用&#xff0c;它为获取和分析商品数据提供了高效途径。本文将详细介绍借助电商 API 接口实现电商…...

32单片机——串口

1、通信 通信的方式可以分为多种&#xff1a; &#xff08;1&#xff09;按照数据传送方式可分为串行通信和并行通信&#xff1b; ①串行通信 基本特征&#xff1a;数据逐位顺序依次传输 优点&#xff1a;传输线少、布线成本低、灵活度高等优点&#xff0c;一般用于近距离人…...

6.应用层

6. 应用层 1. 概述 应用层是计算机网络体系结构的最顶层&#xff0c;是设计和建立计算机网络的最终目的&#xff0c;也是计算机网络中发展最快的部分 早期基于文本的应用&#xff08;电子邮件、远程登录、文件传输、新闻组&#xff09;20世纪90年代将因特网带入千家万户的万维…...

【鸿蒙HarmonyOS】一文详解华为的服务卡片

7.服务卡片 1.什么是卡片 Form Kit&#xff08;卡片开发服务&#xff09;提供一种界面展示形式&#xff0c;可以将应用的重要信息或操作前置到服务卡片&#xff08;以下简称“卡片”&#xff09;&#xff0c;以达到服务直达、减少跳转层级的体验效果。卡片常用于嵌入到其他应…...

深度卷积模型:案例研究

1 为什么要进行案例研究&#xff1f; 过去&#xff0c;计算机视觉中的大量研究都集中在如何将卷积层、池化层以及全连接层这些基本组件组合起来&#xff0c;形成有效的卷积神经网络。 找感觉的最好方法之一就是去看一些示例&#xff0c;就像很多人通过看别人的代码来学习编程一…...

BBR 的 RTT 公平性问题求解

如果 BBR 要跟 reno/cubic 公平&#xff0c;只能顾此失彼&#xff0c;没有任何变通方法&#xff0c;唯一的方法就是在放弃 reno/cubic&#xff0c;但前提你得保证 BBR 流之间是公平的。如果非要照顾 reno/cubic&#xff0c;那就必须要变成 reno/cubic&#xff0c;这就是 BBRv2/…...