色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于Qt 5.15源碼來(lái)聊聊隱式共享

嵌入式小生 ? 來(lái)源:嵌入式小生 ? 2023-02-12 16:52 ? 次閱讀

一、導(dǎo)讀

在實(shí)際開(kāi)發(fā)中,Qt中很多類可以直接作為函數(shù)參數(shù)傳遞,這是為什么?其背后的實(shí)現(xiàn)機(jī)制又是什么?這些都?xì)w功于隱式共享,本文基于Qt 5.15源碼,來(lái)聊聊隱式共享!

二、隱式共享簡(jiǎn)介

Qt中的許多C++類使用隱式數(shù)據(jù)共享來(lái)提高資源使用并減少數(shù)據(jù)復(fù)制。當(dāng)這些類作為參數(shù)傳遞時(shí),因?yàn)橹粋鬟f一個(gè)指向數(shù)據(jù)的指針,并且只有當(dāng)函數(shù)寫(xiě)入數(shù)據(jù)時(shí)數(shù)據(jù)才會(huì)被復(fù)制,即copy -on-write,隱式共享類是安全、高效的。

共享類由一個(gè)指向包含引用計(jì)數(shù)數(shù)據(jù)的共享數(shù)據(jù)塊的指針組成。

當(dāng)創(chuàng)建共享對(duì)象時(shí),它將引用計(jì)數(shù)設(shè)置為1。每當(dāng)有新對(duì)象引用共享數(shù)據(jù)時(shí),引用計(jì)數(shù)就遞增,當(dāng)對(duì)象解引用共享數(shù)據(jù)時(shí),引用計(jì)數(shù)就遞減,當(dāng)引用計(jì)數(shù)變?yōu)榱銜r(shí),將刪除共享數(shù)據(jù)。

在處理共享對(duì)象時(shí),有兩種方法復(fù)制對(duì)象。也就是經(jīng)常談到的:深度拷貝淺拷貝。深度拷貝意味著復(fù)制一個(gè)對(duì)象,淺拷貝是一個(gè)引用拷貝,也就是一個(gè)指向共享數(shù)據(jù)塊的指針。站在內(nèi)存和CPU角度,執(zhí)行一個(gè)深度拷貝可能是昂貴的操作,執(zhí)行淺拷貝則非常快,因?yàn)闇\拷貝只涉及設(shè)置指針和增加引用計(jì)數(shù)。

注意:隱式共享對(duì)象的對(duì)象賦值(operator=())是使用淺拷貝實(shí)現(xiàn)的。

隱式共享的優(yōu)點(diǎn)是:

(1)程序不需要進(jìn)行不必要的數(shù)據(jù)復(fù)制操作,從而減少內(nèi)存的使用和多次執(zhí)行數(shù)據(jù)復(fù)制操作。

(2)可以很容易地被賦值。

(3)可以作為函數(shù)參數(shù)傳遞,并從函數(shù)中返回。

三、源碼角度分析隱式共享

隱式共享會(huì)自動(dòng)將對(duì)象從共享塊中分離出來(lái),如果對(duì)象即將改變并且引用計(jì)數(shù)大于1,(這通常被稱為寫(xiě)時(shí)復(fù)制或值語(yǔ)義。)

隱式共享類可以控制其內(nèi)部數(shù)據(jù),在任何修改其數(shù)據(jù)的成員函數(shù)中,它都會(huì)在修改數(shù)據(jù)之前自動(dòng)分離。(但是,需注意容器迭代器的特殊情況,后文將說(shuō)明這一點(diǎn)!)

此處以QPen這個(gè)隱式共享類為例,從源碼角度分析QPen類是如何從更改內(nèi)部數(shù)據(jù)的成員函數(shù)中分離共享數(shù)據(jù)的。在Qt5.15源碼中用于描述QPen的文件為qpen_p.h、qpen.cpp、qpen.h三個(gè)文件,位于源碼路徑(/qtbase/src/gui/painting目錄)下。在QPen類定義中有一個(gè)detach():

463b7818-aaae-11ed-bfe3-dac502259ad0.png

實(shí)現(xiàn)如下:

46767288-aaae-11ed-bfe3-dac502259ad0.png

detach()用于從共享pen數(shù)據(jù)中分離,以確保該pen只有一個(gè)引用數(shù)據(jù),如果多個(gè)pen共享公共數(shù)據(jù),這支pen將取消對(duì)數(shù)據(jù)的引用并獲得數(shù)據(jù)的副本;如果只有一個(gè)則返回,什么也不做。上述代碼中,QPenData實(shí)則是QPenPrivate的類型別名,用于描述QPen的數(shù)據(jù),定義如下(位于qpen_p.h文件中):

46a27798-aaae-11ed-bfe3-dac502259ad0.png46bc3426-aaae-11ed-bfe3-dac502259ad0.png

上述代碼分析了detach()函數(shù),下文以QPen的一個(gè)成員函數(shù)setStyle(Qt::PenStyle style)來(lái)描述,該函數(shù)實(shí)現(xiàn)如下:

4723201e-aaae-11ed-bfe3-dac502259ad0.png

從上述圖片所示,在setStyle()函數(shù)中,會(huì)使用detach()從公共數(shù)據(jù)中分離,然后在設(shè)置style成員。

綜上,如果Qt提供的類支持隱式共享,那么其源碼內(nèi)部實(shí)現(xiàn)都有對(duì)應(yīng)的數(shù)據(jù)管理機(jī)制,實(shí)現(xiàn)寫(xiě)時(shí)復(fù)制。

四、隱式共享在開(kāi)發(fā)中的使用

上述第二節(jié)描述了隱式共享的QPen類如何從更改內(nèi)部數(shù)據(jù)的成員函數(shù)中分離共享數(shù)據(jù)。可簡(jiǎn)化為下述代碼片段:

voidQPen::setStyle(Qt::PenStyles)
{
detach();//從公共數(shù)據(jù)中分離
d->style=s;//設(shè)置style成員
}

voidQPen::detach()
{
if(d->ref!=1){
...//執(zhí)行深度拷貝
}
}

所以,在開(kāi)發(fā)中如果更改了對(duì)象,類將自動(dòng)與公共數(shù)據(jù)分離,甚至不會(huì)注意到這些對(duì)象是共享的。因此,可以將它們的單獨(dú)實(shí)例視為單獨(dú)的對(duì)象,它們始終作為獨(dú)立的對(duì)象。但在有些情況下可以共享數(shù)據(jù),因此可以將這些類的實(shí)例作為參數(shù)按值傳遞給函數(shù),而不必考慮復(fù)制開(kāi)銷。

例如下列代碼:

QPixmapp1,p2;
p1.load("image.bmp");
p2=p1;//p1和p2共享數(shù)據(jù)

QPainterpaint;
paint.begin(&p2);//將p2從p1中分離出來(lái)
paint.drawText(0,50,"iriczhao");
paint.end();

注:在使用stl風(fēng)格的迭代器時(shí),復(fù)制隱式共享容器(QMap,QList等)需要特別注意。

五、隱式共享迭代器問(wèn)題

對(duì)于stl風(fēng)格的迭代器,在使用隱式共享類時(shí)應(yīng)格外注意。因?yàn)楫?dāng)?shù)髟谌萜魃霞せ顣r(shí),應(yīng)該避免復(fù)制容器。也就是迭代器指向一個(gè)內(nèi)部結(jié)構(gòu),如果復(fù)制一個(gè)容器,此時(shí)應(yīng)特別注意迭代器。例如以下代碼片段:

QLista,b;
a.resize(100000);//創(chuàng)建一個(gè)大列表,里面填滿0。

QList::iteratori=a.begin();

/*-------------------------------------------------------------*/

//使用迭代器i的錯(cuò)誤方法:
b=a;
/*
此時(shí)我們應(yīng)該注意迭代器i,因?yàn)樗鼘⒅赶蚬蚕頂?shù)據(jù)
如果我們執(zhí)行*i=4,那么我們將改變共享實(shí)例(兩個(gè)向量)
其行為不同于STL容器。在Qt中不能這樣做。
*/

/*-------------------------------------------------------------*/

a[0]=5;
/*
容器a現(xiàn)在與共享數(shù)據(jù)分離,
盡管i是容器a的迭代器,但是它現(xiàn)在作為容器b的迭代器工作。
這里的情況是(*i)==0。
*/

b.clear();//現(xiàn)在迭代器i完全無(wú)效了。

intj=*i;//此時(shí)會(huì)出現(xiàn)未定義的行為!
/*
來(lái)自b(i所指向的)的數(shù)據(jù)不見(jiàn)了。
這可以用STL容器(和(*i)==5)定義,
但是這時(shí)候使用QList,可能會(huì)崩潰。
*/

總而言之:當(dāng)?shù)髟谌萜魃霞せ顣r(shí),應(yīng)該避免復(fù)制容器,所有的Qt容器類都應(yīng)該注意這一點(diǎn)。

六、隱式共享類和線程

在Qt中,對(duì)它的許多值類使用了隱式共享進(jìn)行了優(yōu)化,尤其是QImage和QString。從Qt 4開(kāi)始,隱式共享類可以安全地跨線程復(fù)制。這些值類是完全可重入的。

一般情況下,都認(rèn)為隱式共享和多線程是不兼容的概念,因?yàn)橐糜?jì)數(shù)通常不允許這樣做。然而,Qt使用原子引用計(jì)數(shù)來(lái)確保共享數(shù)據(jù)的完整性,避免了引用計(jì)數(shù)器的潛在損壞。

但是需要注意原子引用計(jì)數(shù)不能保證線程安全性。在線程之間共享隱式共享類的實(shí)例時(shí),應(yīng)該適當(dāng)?shù)募渔i進(jìn)行鎖定。這一點(diǎn),與所有重入類(無(wú)論是否共享)相同。原子引用計(jì)數(shù)確實(shí)保證了一個(gè)線程在其自身、隱式共享類的本地實(shí)例上工作是安全的,所以,在開(kāi)發(fā)中可以使用信號(hào)和槽函數(shù)機(jī)制在不同線程之間傳遞數(shù)據(jù),因?yàn)檫@可以在不需要顯式鎖定的情況下完成。

總而言之,Qt 中的隱式共享類實(shí)際上是隱式共享的。即使在多線程應(yīng)用程序中,也可以安全地使用它們,與普通的、非共享的、可重入的基于值的類一樣。






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    11015

    瀏覽量

    215401
  • C++語(yǔ)言
    +關(guān)注

    關(guān)注

    0

    文章

    147

    瀏覽量

    7190
  • 迭代器
    +關(guān)注

    關(guān)注

    0

    文章

    45

    瀏覽量

    4429

原文標(biāo)題:懂Qt,隱式共享都知道嗎?

文章出處:【微信號(hào):嵌入式小生,微信公眾號(hào):嵌入式小生】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 0人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    DLPC350在ubuntu下使用qt5.15編譯SDK時(shí)發(fā)現(xiàn),qt找不到gcc7.5的編譯器,怎么解決?

    在ubuntu下使用qt5.15編譯SDK時(shí)發(fā)現(xiàn),qt找不到gcc7.5的編譯器(已經(jīng)配置了gcc7.5);而在windows下是沒(méi)問(wèn)題的.請(qǐng)問(wèn)ubuntu下該如何編譯呢?
    發(fā)表于 02-18 07:19

    共享三年嵌入項(xiàng)目資料(源碼+實(shí)物圖+原創(chuàng))(申精帖)!

    . 醫(yī)學(xué)圖像系統(tǒng)(只支持大部分的CT,DR,CR)十二STM32F103VBT6超屏解決OV7660高速數(shù)據(jù)同步讀取十三.DIY的wav播放器(有圖有源碼)十四. DIY的STM32驅(qū)動(dòng)OV7660
    發(fā)表于 04-13 15:25

    手動(dòng)編譯QT源碼生成qmake

    交叉編譯QT4.8.7源碼生成qmake工具TQ-i.MX6UL使用的QT版本是QT4.8.7,板卡出廠前附帶的開(kāi)發(fā)資料中,天嵌官方?jīng)]有為開(kāi)發(fā)者編譯生成qmake工具。因此,為了后續(xù)進(jìn)
    發(fā)表于 11-05 08:20

    qt源碼庫(kù)在樹(shù)莓派中的部署方法

    接安裝qt。本文介紹最普遍的部署方式,就是在pc端的ubuntu中交叉編譯庫(kù)源碼,然后上傳編譯好的庫(kù)到樹(shù)莓派,最后配置qt creator交叉編譯的kit來(lái)實(shí)現(xiàn)在pc端編譯自碼程序,上
    發(fā)表于 12-24 06:44

    請(qǐng)問(wèn)QT怎么實(shí)現(xiàn)源碼編譯?

    你好,QT怎么實(shí)現(xiàn)源碼編譯,
    發(fā)表于 12-31 07:49

    qt源碼編譯安裝遇到的問(wèn)題

    QT源碼make通過(guò)后執(zhí)行make install時(shí)報(bào)錯(cuò)。
    發(fā)表于 12-09 15:56

    推薦使用QT5.14或者QT5.15版本 不要急著升級(jí)到QT6

    ? 推薦使用QT5.14或者QT5.15版本,不建議升級(jí)最新版的QT6,很多你要的功能沒(méi)了,特別是開(kāi)發(fā)上位機(jī)需要的模塊沒(méi)了。 Qt 6.0 中已移除的模塊,以下是不在
    的頭像 發(fā)表于 01-26 16:37 ?4.9w次閱讀

    嵌入Linux的QT版本,嵌入Linux版本Qt5.4快速部署

    關(guān)鍵詞:摘要:Qt是一個(gè)領(lǐng)先的跨平臺(tái)應(yīng)用和UI 開(kāi)發(fā)框架(Framework),使用標(biāo)準(zhǔn)C++,適用于桌面,嵌入和移動(dòng)平臺(tái)。本文著重就利用Boot to Qt軟件包來(lái)實(shí)現(xiàn)
    發(fā)表于 11-01 17:20 ?0次下載
    嵌入<b class='flag-5'>式</b>Linux的<b class='flag-5'>QT</b>版本,嵌入<b class='flag-5'>式</b>Linux版本<b class='flag-5'>Qt</b>5.4快速部署

    嵌入linux安裝qt,嵌入Linux版本Qt5.4快速部署

    摘要:Qt是一個(gè)領(lǐng)先的跨平臺(tái)應(yīng)用和UI 開(kāi)發(fā)框架(Framework),使用標(biāo)準(zhǔn)C++,適用于桌面,嵌入和移動(dòng)平臺(tái)。本文著重就利用Boot to Qt 軟件包來(lái)實(shí)現(xiàn)
    發(fā)表于 11-02 10:51 ?0次下載
    嵌入<b class='flag-5'>式</b>linux安裝<b class='flag-5'>qt</b>,嵌入<b class='flag-5'>式</b>Linux版本<b class='flag-5'>Qt</b>5.4快速部署

    嵌入Linux開(kāi)發(fā)環(huán)境搭建-(6)交叉編譯QT4.8.7源碼生成qmake工具

    交叉編譯QT4.8.7源碼生成qmake工具TQ-i.MX6UL使用的QT版本是QT4.8.7,板卡出廠前附帶的開(kāi)發(fā)資料中,天嵌官方?jīng)]有為開(kāi)發(fā)者編譯生成qmake工具。因此,為了后續(xù)進(jìn)
    發(fā)表于 11-02 13:21 ?3次下載
    嵌入<b class='flag-5'>式</b>Linux開(kāi)發(fā)環(huán)境搭建-(6)交叉編譯<b class='flag-5'>QT</b>4.8.7<b class='flag-5'>源碼</b>生成qmake工具

    Qt ECG Monitor Qt嵌入床旁心電監(jiān)護(hù)儀項(xiàng)目源碼

    Qt ECG Monitor是由Qt-UI開(kāi)發(fā)和維護(hù)的嵌入床旁心電監(jiān)護(hù)儀界面項(xiàng)目。項(xiàng)目提供C++/Python語(yǔ)言,基于Qt5下原生QWidget編譯開(kāi)發(fā),包含以下功能界面:包含Wi
    發(fā)表于 01-10 11:41 ?33次下載
    <b class='flag-5'>Qt</b> ECG Monitor <b class='flag-5'>Qt</b>嵌入<b class='flag-5'>式</b>床旁心電監(jiān)護(hù)儀項(xiàng)目<b class='flag-5'>源碼</b>

    記錄整個(gè)Qt環(huán)境的搭建過(guò)程

    整個(gè)Qt環(huán)境安裝過(guò)程大約花了一個(gè)小時(shí),完成后,在Windows的『開(kāi)始』菜單中也可以找到對(duì)應(yīng)的快捷方式。至此,Qt 5.15就安裝完成啦!
    的頭像 發(fā)表于 09-05 15:13 ?1659次閱讀

    QT設(shè)計(jì)的網(wǎng)絡(luò)助手源碼

    QT設(shè)計(jì)的網(wǎng)絡(luò)助手源碼
    發(fā)表于 09-27 11:46 ?2次下載

    qt設(shè)計(jì)的Google拼音輸入法源碼

    qt設(shè)計(jì)的Google拼音輸入法源碼分享
    發(fā)表于 09-26 17:40 ?5次下載

    qt opencv opencl opengl源碼例程

    qt-opencv-opencl-opengl-源碼例程
    發(fā)表于 09-27 14:42 ?1次下載
    主站蜘蛛池模板: 99九九精品国产高清自在线 | 2022精品福利在线小视频 | 国产午夜精品片一区二区三区 | 国产毛A片久久久久久无码 国产毛A片啊久久久久久A | 国语自产拍在线视频普通话 | 97精品少妇偷拍蜜桃AV | 国产精品久久人妻拍拍水牛影视 | 国产精品久久久久久久久爆乳 | 99精品视频在线观看免费播放 | 色婷婷国产麻豆AV | 久久精品免费看网站 | 欧美日韩久久久精品A片 | 美女被日出水 | 色欲天天婬色婬香影院 | 欧美高清视频www夜色资源网 | 国产乱妇乱子在线播视频播放网站 | 3d在线看小舞被躁视频 | 青青草原在线免费 | 久久久久亚洲日日精品 | 国产精品爽爽久久久久久蜜桃网站 | 污污又黄又爽免费的网站 | 在线观看日本污污ww网站 | 伦理片在线线看手机版 | 亚洲国产精品日本无码网站 | 精品国产麻豆AV无码 | 国产精品视频大全 | 国产成人小视频 | 2022国产麻豆剧传媒剧情 | 午夜伦理:伦理片 | 人妻换人妻AA视频 | 日韩精品欧美亚洲高清有无 | 超碰在线线公开免费视频 | 久久99re热在线观看视频 | 谁有成人网站地址 | 99久久99久久精品免费看子 | 欧美性受xxxx狂喷水 | 欧美特黄99久久毛片免费 | 欧美一区二区三区激情视频 | 亚洲福利区 | 青春草国产成人精品久久 | 一本大道无码AV天堂欧美 |

    電子發(fā)燒友

    中國(guó)電子工程師最喜歡的網(wǎng)站

    • 2931785位工程師會(huì)員交流學(xué)習(xí)
    • 獲取您個(gè)性化的科技前沿技術(shù)信息
    • 參加活動(dòng)獲取豐厚的禮品