国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

深度解讀《深度探索C++對(duì)象模型》之?dāng)?shù)據(jù)成員的存取效率分析(一)

這篇具有很好參考價(jià)值的文章主要介紹了深度解讀《深度探索C++對(duì)象模型》之?dāng)?shù)據(jù)成員的存取效率分析(一)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

接下來(lái)我將持續(xù)更新“深度解讀《深度探索C++對(duì)象模型》”系列,敬請(qǐng)期待,歡迎關(guān)注!也可以關(guān)注公眾號(hào):iShare愛(ài)分享,自動(dòng)獲得推文和全部的文章列表。

在《深度解讀《深度探索C++對(duì)象模型》之C++對(duì)象的內(nèi)存布局》這篇文章中已經(jīng)詳細(xì)分析過(guò)C++的對(duì)象在經(jīng)過(guò)封裝后,在各種情況下的內(nèi)存布局以及增加的成本。本文將進(jìn)一步分析C++對(duì)象在封裝后,數(shù)據(jù)成員的存取的實(shí)現(xiàn)手段及訪(fǎng)問(wèn)的效率。在這里先拋出一個(gè)問(wèn)題,然后帶著問(wèn)題來(lái)一步一步分析,如下面的代碼:

class Point {};
Point p;
Point *pp = &p;
p.x = 0;
pp->x = 0;

上面的代碼中,對(duì)數(shù)據(jù)成員x的存取成本是什么?通過(guò)對(duì)象p來(lái)存取成員x和通過(guò)對(duì)象的指針pp來(lái)存取成員x的效率存在差異嗎?要搞清楚這個(gè)問(wèn)題,得看具體的Point類(lèi)的定義以及成員x的聲明方式。Point類(lèi)可能是一個(gè)獨(dú)立的類(lèi)(也就是沒(méi)有從其他類(lèi)繼承而來(lái)),也可能是一個(gè)單一繼承或者多重繼承而來(lái)的類(lèi),甚至也有可能它的繼承父類(lèi)中有一個(gè)是虛擬基類(lèi)(virtual base class),成員x的聲明可能是靜態(tài)的或者是非靜態(tài)的。下面的幾節(jié)將根據(jù)不同的情況來(lái)一一分析。

類(lèi)對(duì)象的數(shù)據(jù)成員的存取效率分析系列篇幅比較長(zhǎng),所以根據(jù)不同的類(lèi)的定義劃分為幾種情形來(lái)分析,這篇先來(lái)分析靜態(tài)數(shù)據(jù)成員的情況。

靜態(tài)數(shù)據(jù)成員在編譯器里的實(shí)現(xiàn)

在前面的文章中說(shuō)過(guò),類(lèi)中的靜態(tài)數(shù)據(jù)成員是跟類(lèi)相關(guān)的,而非跟具體的對(duì)象有關(guān),它存儲(chǔ)在對(duì)象之外,具體的存儲(chǔ)位置是在程序中的數(shù)據(jù)段中。它其實(shí)跟一個(gè)全局變量沒(méi)什么區(qū)別,在編譯期間編譯器就已經(jīng)確定好了它的存儲(chǔ)位置,所以能夠確定它的地址??匆幌孪旅娴拇a:

#include <cstdio>

int global_val = 1;

class Base {
public:
    int b1;
    static int s1;
};
int Base::s1 = 1;

int main() {
    static int static_var = 1;
    int local_var = 1;
    Base b;
    printf("&global_val = %p\n", &global_val);
    printf("&static_var = %p\n", &static_var);
    printf("&local_var = %p\n", &local_var);
    printf("&b.b1 = %p\n", &b.b1);
    printf("&b.s1 = %p\n", &b.s1);

    return 0;
}

程序輸出的結(jié)果:

&global_val = 0x102d74000
&static_var = 0x102d74008
&local_var = 0x16d0933f8
&b.b1 = 0x16d0933f4
&b.s1 = 0x102d74004

可以看到全局變量global_val和局部靜態(tài)變量static_var以及類(lèi)中的靜態(tài)數(shù)據(jù)成員s1的地址是順序且緊密排列在一起的,而且跟其他的兩個(gè)局部變量的地址相差較大,說(shuō)明這幾個(gè)都是一起存儲(chǔ)在程序的數(shù)據(jù)段中的。類(lèi)中的非靜態(tài)數(shù)據(jù)成員b1跟局部變量local_var一樣,是存放在棧中的。

可以進(jìn)一步看看生成的匯編代碼,看一下是怎么存取靜態(tài)數(shù)據(jù)成員的,下面節(jié)選部分的匯編代碼:

main:                            # @main
    # 略...
    lea     rdi, [rip + .L.str]
    lea     rsi, [rip + global_val]
    mov     al, 0
    call    printf@PLT
    lea     rdi, [rip + .L.str.1]
    lea     rsi, [rip + main::static_var]
    mov     al, 0
    call    printf@PLT
  	# 略...
    lea     rdi, [rip + .L.str.4]
    lea     rsi, [rip + Base::s1]
    mov     al, 0
    call    printf@PLT
    # 略...
    ret
global_val:
    .long   1        # 0x1

Base::s1:
    .long   1        # 0x1

main::static_var:
    .long   1        # 0x1

從匯編代碼中看到,global_valBase::s1main::static_var是定義在數(shù)據(jù)段中的,在代碼中直接使用它們的地址,如:

lea rsi, [rip + Base::s1]

則是將Base::s1的地址加載到rsi寄存器中,作為參數(shù)傳遞給printf函數(shù)。這也證明了它跟全局變量,普通的靜態(tài)變量是沒(méi)有區(qū)別的。結(jié)論就是,類(lèi)中的靜態(tài)數(shù)據(jù)成員的存取方式是直接通過(guò)一個(gè)具體的地址來(lái)訪(fǎng)問(wèn)的,跟全局變量毫無(wú)區(qū)別,所以效率上也跟訪(fǎng)問(wèn)一個(gè)全局變量一樣。

通過(guò)不同方式存取靜態(tài)數(shù)據(jù)成員的效率差異

訪(fǎng)問(wèn)類(lèi)的靜態(tài)數(shù)據(jù)成員可以通過(guò)類(lèi)名來(lái)訪(fǎng)問(wèn),如Base::s1,也可以通過(guò)對(duì)象來(lái)訪(fǎng)問(wèn),如b.s1,甚至是通過(guò)指針來(lái)訪(fǎng)問(wèn),如pb->s1。那么這幾種訪(fǎng)問(wèn)方式有什么差別?或者說(shuō)是否有效率上的損失?其實(shí)這幾種訪(fǎng)問(wèn)方式本質(zhì)上沒(méi)有任何差別,編譯器會(huì)轉(zhuǎn)換成如Base::s1一樣的方式,后面的兩種方式只是語(yǔ)法上的方便而已,看一下匯編代碼就一目了然。把上面的例子多余的代碼刪除掉,只留下Base類(lèi),然后main函數(shù)中增加幾行打印,如下:

Base b;
Base *pb = &b;
printf("&Base::s1 = %p\n", &Base::s1);
printf("&b.s1 = %p\n", &b.s1);
printf("&pb->s1 = %p\n", &pb->s1);

輸出的結(jié)果當(dāng)然是同一個(gè)地址了,下面是節(jié)選的匯編代碼:

lea     rdi, [rip + .L.str]
lea     rsi, [rip + Base::s1]
mov     al, 0
call    printf@PLT
lea     rdi, [rip + .L.str.1]
lea     rsi, [rip + Base::s1]
mov     al, 0
call    printf@PLT
lea     rdi, [rip + .L.str.2]
lea     rsi, [rip + Base::s1]
mov     al, 0
call    printf@PLT

可以看到C++中的幾行不同的訪(fǎng)問(wèn)方式在匯編代碼中都轉(zhuǎn)換為同樣的代碼:

lea rsi, [rip + Base::s1]

繼承而來(lái)的靜態(tài)數(shù)據(jù)成員的存取分析

我們已經(jīng)知道類(lèi)中的靜態(tài)數(shù)據(jù)成員是跟對(duì)象無(wú)關(guān)的,所有的對(duì)象都共享同一個(gè)靜態(tài)數(shù)據(jù)成員。但是如果繼承而來(lái)的靜態(tài)數(shù)據(jù)成員又是怎樣的呢?假如定義一個(gè)Derived類(lèi),它是Base類(lèi)的派生類(lèi),那么靜態(tài)數(shù)據(jù)成員s1的情況又是如何?其實(shí)無(wú)論繼承多少次,靜態(tài)數(shù)據(jù)成員都只有一份,無(wú)論是Derived類(lèi)還是Base類(lèi),它們都共享同一個(gè)靜態(tài)數(shù)據(jù)成員s1,可以通過(guò)下面的例子來(lái)驗(yàn)證一下:

#include <cstdio>

class Base {
public:
    int b1;
    static int s1;
};
int Base::s1 = 1;

class Derived: public Base {};

int main() {
    Derived d;
    printf("&d.s1 = %p\n", &d.s1);
    printf("d.s1 = %d\n", d.s1);
    d.s1 = 2;

    Base b;
    printf("&b.s1 = %p\n", &b.s1);
    printf("b.s1 = %d\n", b.s1);

    return 0;
}

程序輸出的結(jié)果:

&d.s1 = 0x10028c000
d.s1 = 1
&b.s1 = 0x10028c000
b.s1 = 2

可以看到通過(guò)Derived類(lèi)的對(duì)象dBase類(lèi)的對(duì)象b訪(fǎng)問(wèn)到的都是同一個(gè)地址,通過(guò)對(duì)象d修改s1后,通過(guò)對(duì)象b可以看到修改后的值。

如果您感興趣這方面的內(nèi)容,請(qǐng)?jiān)谖⑿派纤阉鞴娞?hào)iShare愛(ài)分享并關(guān)注,以便在內(nèi)容更新時(shí)直接向您推送。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-855039.html

到了這里,關(guān)于深度解讀《深度探索C++對(duì)象模型》之?dāng)?shù)據(jù)成員的存取效率分析(一)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 深度解讀《深度探索C++對(duì)象模型》之C++虛函數(shù)實(shí)現(xiàn)分析(二)

    接下來(lái)我將持續(xù)更新“深度解讀《深度探索C++對(duì)象模型》”系列,敬請(qǐng)期待,歡迎關(guān)注!也可以關(guān)注公眾號(hào):iShare愛(ài)分享,自動(dòng)獲得推文和全部的文章列表。 第一篇請(qǐng)從這里閱讀: 深度解讀《深度探索C++對(duì)象模型》之C++虛函數(shù)實(shí)現(xiàn)分析(一) 這一篇主要講解多重繼承情況下

    2024年04月24日
    瀏覽(23)
  • 深度解讀《深度探索C++對(duì)象模型》之C++虛函數(shù)實(shí)現(xiàn)分析(一)

    深度解讀《深度探索C++對(duì)象模型》之C++虛函數(shù)實(shí)現(xiàn)分析(一)

    接下來(lái)我將持續(xù)更新“深度解讀《深度探索C++對(duì)象模型》”系列,敬請(qǐng)期待,歡迎關(guān)注!也可以關(guān)注公眾號(hào):iShare愛(ài)分享,自動(dòng)獲得推文和全部的文章列表。 假如有這樣的一段代碼,代碼中定義了一個(gè)Object類(lèi),類(lèi)中有一個(gè)成員函數(shù)print,通過(guò)以下的兩種調(diào)用方式調(diào)用: 請(qǐng)問(wèn)這

    2024年04月23日
    瀏覽(39)
  • C++類(lèi)和對(duì)象-C++對(duì)象模型和this指針->成員變量和成員函數(shù)分開(kāi)存儲(chǔ)、this指針概念、空指針訪(fǎng)問(wèn)成員函數(shù)、const修飾成員函數(shù)

    C++類(lèi)和對(duì)象-C++對(duì)象模型和this指針->成員變量和成員函數(shù)分開(kāi)存儲(chǔ)、this指針概念、空指針訪(fǎng)問(wèn)成員函數(shù)、const修飾成員函數(shù)

    #includeiostream using namespace std; //成員變量 和 成員函數(shù) 分開(kāi)儲(chǔ)存的 class Person { public: ?? ?Person() { ?? ??? ?mA = 0; ?? ?} ?? ?//非靜態(tài)成員變量占對(duì)象空間 ?? ?int mA; ?? ?//靜態(tài)成員變量不占對(duì)象空間 ?? ?static int mB; ?? ?//函數(shù)也不占對(duì)象空間,所有函數(shù)共享一個(gè)函數(shù)實(shí)例

    2024年02月20日
    瀏覽(24)
  • [C++]類(lèi)與對(duì)象(下) -- 初始化列表 -- static成員 -- 友元 -- 內(nèi)部類(lèi),一篇帶你深度了解。

    [C++]類(lèi)與對(duì)象(下) -- 初始化列表 -- static成員 -- 友元 -- 內(nèi)部類(lèi),一篇帶你深度了解。

    ? 目錄 1、再談構(gòu)造函數(shù) 1.1 構(gòu)造函數(shù)體賦值 1.2 初始化列表 1.2.1 初始化列表的意義 1.3 explicit 2、static成員 2.1 問(wèn)題引入 2.2 特性 3、友元 3.1 友元函數(shù) 3.2 友元類(lèi) 4、內(nèi)部類(lèi) 在創(chuàng)建對(duì)象時(shí),編譯器通過(guò)調(diào)用構(gòu)造函數(shù),給對(duì)象中各個(gè)成員變量一個(gè)合適的初始值。 我們構(gòu)造函

    2024年02月12日
    瀏覽(24)
  • C++奇跡之旅:探索類(lèi)對(duì)象模型內(nèi)存的存儲(chǔ)猜想

    C++奇跡之旅:探索類(lèi)對(duì)象模型內(nèi)存的存儲(chǔ)猜想

    上回我們學(xué)習(xí)了類(lèi)的定義,初步了解了什么是類(lèi)?類(lèi)的定義,以及類(lèi)的三個(gè)訪(fǎng)問(wèn)限定符: public , private , protected ,本小節(jié)將講解類(lèi)的實(shí)例化,類(lèi)對(duì)象模型的猜想存儲(chǔ),及三種簡(jiǎn)單類(lèi)的計(jì)算。 在 C++ 中,類(lèi)的實(shí)例化是指創(chuàng)建一個(gè)類(lèi)的對(duì)象。當(dāng)我們定義了一個(gè)類(lèi)之后,就可以根據(jù)

    2024年04月12日
    瀏覽(20)
  • C++:常成員變量、常成員函數(shù)、常對(duì)象

    C++:常成員變量、常成員函數(shù)、常對(duì)象

    常成員變量: 1.用const修飾,可位于類(lèi)型前后,若是成員變量類(lèi)型為指針則只可位于類(lèi)型后。 即:int? *const? p; 2.只能通過(guò)構(gòu)造函數(shù)的初始化表對(duì)常成員變量進(jìn)行初始化。 3.常成員所在類(lèi)中的所有構(gòu)造函數(shù)都必須對(duì)常成員變量初始化(通過(guò)初始化表)。 4.常成員變量可以被訪(fǎng)

    2024年02月11日
    瀏覽(34)
  • C++ ------類(lèi)和對(duì)象詳解六大默認(rèn)成員函數(shù)

    C++ ------類(lèi)和對(duì)象詳解六大默認(rèn)成員函數(shù)

    如果我們定義一個(gè)類(lèi),然后這個(gè)類(lèi)中什么也沒(méi)有。那么這里的類(lèi)就什么也沒(méi)有嗎?其實(shí)不然,任何類(lèi)在里面什么都不寫(xiě)時(shí),編譯器都會(huì)生成6個(gè)默認(rèn)成員函數(shù)。 用戶(hù)沒(méi)有顯式實(shí)現(xiàn),編譯器會(huì)生成的成員函數(shù)稱(chēng)為默認(rèn)成員函數(shù)。 六個(gè)默認(rèn)成員函數(shù) 我們來(lái)看一個(gè)Date類(lèi) 觀察上述代

    2024年02月15日
    瀏覽(28)
  • 【C++】類(lèi)和對(duì)象(中篇)----->六大默認(rèn)成員函數(shù)

    【C++】類(lèi)和對(duì)象(中篇)----->六大默認(rèn)成員函數(shù)

    目錄 一、類(lèi)的6個(gè)默認(rèn)成員函數(shù) 二、構(gòu)造函數(shù) ?1、概念? ?2、特性 三、析構(gòu)函數(shù) ?1、概念 ?2、特性 四、拷貝構(gòu)造函數(shù) ?1、概念 ?2、特征 五、賦值運(yùn)算符重載 ?1、運(yùn)算符重載 ?2、值運(yùn)算符重載 ? ?2.1?賦值運(yùn)算符重載格式 ? ?2.2?賦值運(yùn)算符只能重載成類(lèi)的成員函數(shù)不能

    2024年02月12日
    瀏覽(26)
  • 【C++系列P5】‘類(lèi)與對(duì)象‘-三部曲——[對(duì)象&特殊成員](3/3)

    【C++系列P5】‘類(lèi)與對(duì)象‘-三部曲——[對(duì)象&特殊成員](3/3)

    ?前言 大家好吖,歡迎來(lái)到 YY 滴 C++系列 ,熱烈歡迎! 【 \\\'類(lèi)與對(duì)象\\\'-三部曲】的大綱主要內(nèi)容如下 : 如標(biāo)題所示,本章是【 \\\'類(lèi)與對(duì)象\\\'-三部曲】三章中的第三章節(jié)——對(duì)象成員章節(jié),主要內(nèi)容如下: 目錄 一.const成員/成員函數(shù) 一.用const修飾this指針的好處——含權(quán)限知識(shí)點(diǎn)

    2024年02月06日
    瀏覽(22)
  • 【C++入門(mén)到精通】C++入門(mén) —— 類(lèi)和對(duì)象(初始化列表、Static成員、友元、內(nèi)部類(lèi)、匿名對(duì)象)

    【C++入門(mén)到精通】C++入門(mén) —— 類(lèi)和對(duì)象(初始化列表、Static成員、友元、內(nèi)部類(lèi)、匿名對(duì)象)

    目錄 一、初始化列表 ?初始化列表概念 ?初始化列表的優(yōu)點(diǎn) ?使用場(chǎng)景 ?explicit 二、Static成員 ?Static成員概念 ??靜態(tài)數(shù)據(jù)成員: ??靜態(tài)函數(shù)成員: ?使用靜態(tài)成員的優(yōu)點(diǎn) ?使用靜態(tài)成員的注意事項(xiàng) 三、友元 ?友元的概念 ?類(lèi)友元 ?函數(shù)友元 ?四、內(nèi)部類(lèi) ?

    2024年02月14日
    瀏覽(16)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包