Qt 验证自动释放 + 乱码问题(6)

文章目录

  • 验证自动释放(对象树上的对象)
  • 乱码问题的缘由
  • 解决乱码问题
    • 1. 使用QString
    • 2. qDebug()
  • 小结

简介:上一篇文章写到,当new出一个控件对象并且将它挂到对象树上,无需我们手动释放该对象,是因为在一个合适的时机,会统一释放该对象树上的控件对象。这篇文章主要内容是去验证确实会自动释放该对象树上的控件对象,并且讨论Qt终端输出的乱码问题的缘由,并且如何去解决乱码问题,并且对这两篇文章的内容做个小结,也能由此看出,虽然只是一个简单的hello world程序,却能连续许多的相关知识点(全是干货)

验证自动释放(对象树上的对象)

先创建一个项目,再左上角找到文件,新建一个项目,此时选择新添加类

在这里插入图片描述

这里输入你添加类的名称后,选择它的基类。如果点开三角没看到,就直接手动输入QLabel,其它的就不用管了,直接下一步

在这里插入图片描述

完成后,左边文件就会自动添加mylabel.h与mylabel.cpp

// mylabel.h
#ifndef MYLABEL_H
#define MYLABEL_Hclass myLabel : public QLabel
{
public:myLabel();
};#endif // MYLABEL_H// mylabel.cpp
#include "mylabel.h"myLabel::myLabel()
{}

我们会发现添加的mylabel.h,它并没有包含头文件 QLabel.h,这操作其实挺挫的,帮我们生成了一些代码,但好像又没完全生成,连头文件都没有自动包含,那也没啥办法,就只能手动的去包含。不过,它生成的默认构造很明显也不是我们需要的,得手动写 mylabel(QWidget* parent),这样才能确保咱们自己的对象能够加到对象树上

#ifndef MYLABEL_H
#define MYLABEL_H
#include<QLabel>class myLabel : public QLabel
{
public:myLabel(QWidget* parent);
};#endif // MYLABEL_H

处理完mylabel.h文件,再来看看mylabel.cpp文件。这里分享一个小技巧,在Qt Creator中,可以通过F4快捷键快速切换.h和对应的.cpp文件,这也是C++IDE的常规功能下面构造函数中,QLabel(parent) 它会调用父类的构造函数去初始化,这样才能让咱们自己类的对象加入到Qt 对象树上,具体看Widget.cpp文件的代码

#include "mylabel.h"
myLabel::myLabel(QWidget* parent) : QLabel(parent)
{
}

完成了mylabel.hmylabel.cpp,接下来Widget.cpp文件的操作就是复刻Qt 创建hello world程序的操作了,看看myLabel(this);这就是为啥要手动写构造函数的缘故

#include "widget.h"
#include "ui_widget.h"
#include "mylabel.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);myLabel* label = new myLabel(this);label->setText("hello world");
}Widget::~Widget()
{delete ui;
}

写到这里界面上已经能显示出hello world了,但如何去观察该对象会自动释放呢?那对象要自动释放,是不是只能从析构函数入手,所有只需要在 myLabel类中写个析构函数即可判断这里再分享一个小技巧,在写完一个函数的声明后,按下 alt + enter就可以自动在对应的cpp文件中添加函数的定义了

class myLabel : public QLabel
{
public:myLabel(QWidget* parent);~myLabel();// 先写析构函数的声明
};

它如果会自动释放对象的话,是一定会走析构函数的,可能会遇到点疑问(其实是我自己搞蒙了,嘿嘿)?为啥这析构函数不去delete 对象呢?首先要分清楚咱现在探究的是new出的这个对象我们没有delete,它却会自动释放,那它释放是肯定要去走析构函数的啊,其次它的成员变量也没有指向一块空间的啊,所有不需要在析构函数中delete啥

myLabel::~myLabel()
{std::cout << "Mylabel已经被销毁" << std::endl;
}

当你运行程序时,你会发现下面的应用程序输出啥也没有,这是因为你还没有关闭界面,没有自动释放,关闭界面后会看到应用输出程序输出中显示:Mylabel宸茬粡琚攢姣,这有是有了但咋是乱码呢?那这证明了该对象会自动析构,现在迎来了一个新问题:乱码的缘由是什么,如何去解决乱码

在这里插入图片描述

乱码问题的缘由

在这里插入图片描述

通过上述的验证,有日志显示就说明了析构函数是执行了,虽然没有手动delete,但是由于把MyLabel挂到了对象树上,此时窗口销毁的时候,就会自动销毁对象树中的所有对象,MyLabel的析构时执行到了。但实际的显示结果却出现乱码,乱码这个事情咱们以后是会经常遇到的而乱码问题出现的原因有且只有一个(不局限于C++)就是编码方式不匹配

那编码方式不匹配是啥意思呢?就是如果你字符串本身是utf8编码的,但是终端(控制台)却是按照 gbk(后面解释)的方式来解析显示的,此时就会出现乱码。(就好像是拿着 utf8 的数值就查询 gbk 的码表,那能对才见了鬼了,此时就会出现乱码

  • 现在咱提出一个问题,一个汉字占多少个字节。这还用想吗?在C语言中就知道一个汉字占两个字节,但真的是这样的吗?其实针对这个问题来说,只要你回答出一个具体的数字,那就一定是错的!回答这个问题之前,要考虑到它的前提条件:也就是当前中文编码使用的是哪种方式(字符集)
  • 大家都知道计算机中只存储二进制数字,那英文字母怎么表示的呢?就是通过ASCII码表去规定每个字符都有一个对应的数字去表示,而表示英文只需要用到一个字节(也就八个比特位),毕竟英文字母数量就那么几个。而表示中文一个字节根本不够,因为中文常用字就大概四千个,算上生僻字就有差不多六万个左右。
  • 通过ASCII码表去规定英文字母和一些字符,那自然会有一个大表格会给每个汉字去分配一个整数(计算机只要把这六万个左右的整数以及对应的汉字直接存起来,遇到相应的表示汉字的二进制数字,再根据这张表找到对应的汉字输出即可,而对于计算机来说,六万多个符号的表格就是小case)
  • 那具体这个表格是什么样子的呢?具体每个汉字都使用哪个数字表示?这就不一定了,这个表示汉字的字符集有很多种,而不同的字符集表示同一个汉字,所使用的数字各不相同。
  • 目前表示汉字字符集主要有两种方式,第一种:GBK 使用2个字节表示一个汉字,其中Windows简体中文版,默认的字符集就是GBK。第二种:UTF-8 / utf8 变长编码,它表示一个符号,使用的字节数有变化(2-4个)但是在utf8中,一个汉字一般是3个字节,其中Linux默认就是 utf8
  • 一个汉字它具体的utf8 / GBK 编码的数值是多少,可以通过一些在线工具查看

std::cout << "Mylabel已经被销毁" << std::endl;这个字符串使用的编码方式和当前mylabel.pp文件的编码方式是一致的,如何去查看该文件的编码方式呢?以记事本打开.cpp文件后,在将该文件另存为,就可以看到该文件的编码方式了,如果下面显示的是 ANSI,则说明这个文件是GBK编码

在这里插入图片描述

那现在终端出现了乱码,那就证明Qt Creator内置的终端不是以 utf8 的方式来显示字符串的,另外该终端好像无法去设置字符编码,但可以从其它的方式入手

解决乱码问题

1. 使用QString

QString可以去帮助我们自动的处理编码方式,这了解一下就行了,谁会去用这玩意啊。所以着重介绍第二种方法

myLabel::~myLabel()
{QString str("Mylabel已经被销毁");fprintf(stdout, "%s", str.toLocal8Bit().constData());
}

2. qDebug()

Qt其实提供了专门用来打印日志的工具,也就是qDebug()工具,借助这个就可以完成打印日志的过程,还能很好处理字符编码(就无需我们去关注内部啦),这用起来嘎嘎的香。这里咱阐述一下qDebug(),它是一个宏,里面封装了一个QDebug对象,而只需要直接使用qDebug()就行了,它这里其实就相当于重载了 “<<” 移位运算符去输出(没说它就是重载哈),可以把它当成cout来使用

#include<QDebug>
myLabel::~myLabel()
{qDebug() << "Mylabel已经被销毁了";
}

后续使用Qt ,如果想通过打印日志的方式输出一些调试信息,都优先使用 qDebug。虽然使用 cout 也行,但是cout 对于编码的处理不太好,在windows 上容易出现乱码(如果是 Linux使用 Qt Creator,一般就没事了,Linux 默认的编码一般都是 utf8)。而且使用qDebug,还有一个好处就是:打印的调试日志,是可以统一进行关闭的!因为输出的日志,其实是开发阶段,调试程序的时候使用的。但你将程序发布给用户,是不希望用户看到这些日志的!而qDebug 可以通过编译开关,来实现一键式关闭)具体如何去关闭,加个宏就OK了(网上搜就直接出来了,这里就不过多介绍了)

小结

  1. 认识QLabel类,能够在界面上显示字符串,通过 setText 来设置参数QString (Qt中把C++里的很多容器类,进行了重新封装以及历史原因)
  2. 内存泄露/文件资源泄露
  3. 对象树,Qt中通过对象树来统一的释放界面的控件对象,Qt 还是推荐使用 new的方式在堆上创建对象,通过对象树去统一释放对象,其次创建对象的时候,在构造函数中要指定父对象(此时才会挂到对象树上),如果你的对象没有挂到对象树上,就必须要记得手动释放!
  4. 通过继承自Qt内置的类,就可以达到对现有控件进行功能扩展效果(因为Qt 内置的 QLabel是没法看到销毁过程的,那为了看清楚,就自己去创建类MyLabel,继承自 QLabel,再重写析构函数,在析构函数中,加上日志就能直观的观察到对象释放的过程了)其实面向对象"继承",本质上是对现有代码进行的"扩展"当然也可以重写控件中的任何功能,不仅仅是析构函数,后期学习总有一些控件是达不到要求的,那此时就得去功能扩展
  5. 乱码问题和字符集~MySQL(很多地方都涉及到)
  6. 如何在Qt 中打印日志,作为调试信息。使用cout固然可以,但是并不是上策(字符编码处理的不好,也不方便统一进行关闭)Qt 中推荐使用qDebug()完成日志的打印。那之前调试程序都是用调试器(VS/gdb),为啥要打印日志调试呢?(因为有时调试器很多时候是有局限性的,是无法使用的,比如说,假设当前存在的 bug是一个概率性的 bug,出现的概率是1%甚至更小,如果要想去调试,那得调多少次才会出现这一次bug,但如果我们去使用日志,就可以很好的解决这种问题,我直接让这个代码按照逻辑循环走几万次,总会出现几次bug吧,不过无论是哪种方式,本质上都是观察程序执行的中间过程和中间结果

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

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

相关文章

fastjson2 json.tojsonstring 会自动忽略过滤掉 key: null的数据

如果你想在序列化时保留值为 null 的字段&#xff0c;只要打开 Fastjson2 的 WriteNulls 特性即可。常见做法有两种——按调用级别开启&#xff0c;或全局开启。 1. 在每次序列化时加 WriteNulls import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONWriter…

LeetCode热题100--54.螺旋矩阵--中等

1. 题目 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5] 示例 2&#xff1a; 输入&#xff1a;ma…

别卷手柄了!跨平台VR遥操系统实现仿真

我们构建了一个基于 Quest 3 的 VR 遥操系统&#xff0c;该系统能够同时支持 DISCOVERSE 仿真环境与 MMK2 真机的操控&#xff0c;实现了从虚拟环境到真实机器人系统的无缝对接。 • 基于 VR 实现的遥操系统具有良好的扩展性和便携性&#xff0c;为多场景应用提供了灵活的操作方…

Linux复习笔记(一)基础命令和操作

遇到的问题&#xff0c;都有解决方案&#xff0c;希望我的博客能为你提供一点帮助。 一、Linux中的基础命令和操作&#xff08;约30%-40%) 1.用户和组&#xff08;5%左右&#xff09; 1.1用户简介&#xff08;了解&#xff09; 要求&#xff1a;了解&#xff0c;知道有三个用户…

【C语言干货】野指针

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、什么是野指针&#xff1f;二、野指针的三大成因 1.指针未初始化2.指针越界访问2.指针指向已释放的内存 前言 提示&#xff1a;以下是本篇文章正文内容&…

Unity:Surface Effector 2D(表面效应器 2D)

目录 什么是表面效应器 2D&#xff1f; &#x1f3af; 它是做什么的&#xff1f; &#x1f9ea; 从第一性原理解释它是怎么工作的 &#x1f4e6; 重要参数解释 为什么不直接用 Rigidbody&#xff08;刚体&#xff09;来控制运动 &#xff1f; 所以什么时候该用哪个&#…

android 记录应用内存

windows cmd下 30s 记录一次 echo off setlocal enabledelayedexpansion set /a counter0 :loop echo %date% %time% >> meminfo.txt adb shell dumpsys meminfo packagename>> meminfo.txt timeout /t 30 /nobreak >nul set /a counter1 echo counter: !coun…

基于神经网络的 YOLOv8、MobileNet、HigherHRNet 姿态检测比较研究

摘要 随着人工智能技术的飞速发展&#xff0c;基于神经网络的姿态检测技术在计算机视觉领域取得了显著进展。本文旨在深入比较分析当前主流的姿态检测模型&#xff0c;即 YOLOv8、MobileNet 和 HigherHRNet&#xff0c;从模型架构、性能表现、应用场景等多维度展开研究。通过详…

解决HomeAssistant 无法安装 samba share问题

最近家里树莓派上的homeassistant 被折腾崩了&#xff0c;重新安装过程中发现加载项“Official add-ons”里面的“samba share”、“file edit”、“Mosquitto broker”等常用组件都不能安装。报以下错误&#xff1a; [supervisor.docker.interface] Cant install homeassista…

[Linux]从零开始的STM32MP157 Buildroot根文件系统构建

一、前言 在前面的教程中&#xff0c;教了大家如何移植一个LInux的内核并且正确启动&#xff0c;我们发现Linux内核在启动后会出现一个错误&#xff0c;提示我们没有找到根文件系统。那么什么是根文件系统呢&#xff1f;之前我们使用Ubuntu编译了STM32MP157的TF-A,UBOOT,LINUX内…

2025-05-07 学习记录--Python-变量 + 常量 + 命名规则 + 变量的数据类型 + 数据类型

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、变量 ⭐️ 多个变量的赋值 &#x1f36d; 二、常量 ⭐️ 程序在运行的过程中&#xff0c;值永远不会发生改变的量称之为常量…

16.状态模式:思考与解读

原文地址:状态模式&#xff1a;思考与解读 更多内容请关注&#xff1a;深入思考与解读设计模式 引言 在开发软件系统时&#xff0c;特别是当对象的行为会随着状态的变化而变化时&#xff0c;系统往往会变得复杂。你是否遇到过这样的情况&#xff1a;一个对象的行为在不同的状…

从 Pretrain 到 Fine-tuning:大模型迁移学习的核心原理剖析

引言 在人工智能领域&#xff0c;大模型的出现掀起了一场技术革命。这些拥有海量参数的模型&#xff0c;如 GPT-4、PaLM 等&#xff0c;在众多任务上展现出了惊人的能力。然而&#xff0c;训练一个大模型需要耗费巨大的计算资源和时间&#xff0c;而且直接让大模型处理特定领域…

Java详解LeetCode 热题 100(11):LeetCode 239. 滑动窗口最大值(Sliding Window Maximum)详解

文章目录 1. 题目描述2. 理解题目3. 解法一&#xff1a;暴力法3.1 思路3.2 Java代码实现3.3 代码详解3.4 复杂度分析3.5 适用场景 4. 解法二&#xff1a;优先队列&#xff08;最大堆&#xff09;4.1 思路4.2 Java代码实现4.3 代码详解4.4 复杂度分析4.5 适用场景 5. 解法三&…

org.apache.poi——将 office的各种类型文件(word等文件类型)转为 pdf

org.apache.poi——将 office的各种类型文件&#xff08;word等文件类型&#xff09;转为 pdf 简介使用方法word转pdf 使用示例word转pdf 简介 使用方法 word转pdf Maven坐标为 <dependency><groupId>com.documents4j</groupId><artifactId>documen…

二叉树与优先级队列

1.树 树是由n个数据构成的非线性结构&#xff0c;它是根朝上&#xff0c;叶朝下。 注意&#xff1a;树形结构之中&#xff0c;子树之间不能连接&#xff0c;不然就不构成树形结构 1.子树之间没有交集 2.除了根节点以外&#xff0c;每一个节点有且只有一个父亲节点 3.一个n个…

如何进行室内VR全景拍摄?

如何进行室内VR全景拍摄&#xff1f; 室内VR全景拍摄作为先进的视觉技术&#xff0c;能够为用户提供沉浸式的空间体验。本文介绍如何进行室内VR全景拍摄&#xff0c;并阐述众趣科技在这一领域的技术支持和服务优势。 室内VR全景拍摄基础 1. 室内VR全景拍摄概述 室内VR全景拍…

如何通过代理 IP 实现异地直播推流

在直播行业日益火爆的今天&#xff0c;许多主播希望突破地域限制&#xff0c;实现异地直播推流&#xff0c;以获得更广泛的观众群体和更好的直播效果。代理 IP 作为一种有效的网络工具&#xff0c;能够帮助主播轻松达成这一目标。本文将详细介绍如何通过代理 IP 实现异地直播推…

随机变量数字特征

主要介绍一维随机变量期望和方差、二维随机变量期望和方差、以及协方差相关公式&#xff0c;及推导。 一维随机变量 以一个抛硬币的场景作为例子&#xff0c;如下&#xff1a; 抛掷两枚均匀硬币&#xff0c;如果两枚都是正面向上&#xff0c;则赢得2元&#xff0c;否则就输掉…

上传图片后,如何调用API进行商品搜索?

以下是一个完整的示例&#xff0c;展示如何在上传图片后调用淘宝按图搜索商品&#xff08;拍立淘&#xff09;API进行商品搜索&#xff1a; 1. 准备工作 注册账号并获取API密钥&#xff1a;在淘宝开放平台注册账号&#xff0c;创建应用&#xff0c;获取app_key和app_secret。 …