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
英文地址,請注明出處:http://en.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。 …