最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c++對(duì)象內(nèi)存布局示例詳解

 更新時(shí)間:2021年10月24日 14:40:49   作者:高性能架構(gòu)探索  
C++類(lèi)的內(nèi)存布局跟結(jié)構(gòu)體有點(diǎn)像,實(shí)際上,類(lèi)中成員變量的內(nèi)存布局規(guī)則跟結(jié)構(gòu)體是一樣的,區(qū)別在于函數(shù),虛函數(shù)的放置,下面這篇文章主要給大家介紹了關(guān)于c++對(duì)象內(nèi)存布局的相關(guān)資料,需要的朋友可以參考下

前言

了解你所使用的編程語(yǔ)言究竟是如何實(shí)現(xiàn)的,對(duì)于C++程序員可能特別有意義。首先,它可以去除我們對(duì)于所使用語(yǔ)言的神秘感,使我們不至于對(duì)于編譯器干的活感到完全不可思議;尤其重要的是,它使我們?cè)贒ebug和使用語(yǔ)言高級(jí)特性的時(shí)候,有更多的把握。當(dāng)需要提高代碼效率的時(shí)候,這些知識(shí)也能夠很好地幫助我們。

簡(jiǎn)單非多態(tài)的內(nèi)存布局

class X {
    int     x;
    float   xx;

public:
    X() {}
    ~X() {}

    void printInt() {}
    void printFloat() {}
};

      |                        |          
      |------------------------| <------ X class object memory layout
      |        int X::x        |
      |------------------------|  stack segment
      |       float X::xx      |       |   
      |------------------------|       |
      |                        |      \|/
      |                        |    
      |                        |
------|------------------------|----------------
      |         X::X()         | 
      |------------------------|       |   
      |        X::~X()         |       |
      |------------------------|      \|/
      |      X::printInt()     |  text segment
      |------------------------|
      |     X::printFloat()    |
      |------------------------|
      |                        |            

在本示例中

  • 只有數(shù)據(jù)成員存儲(chǔ)在堆棧中,且其聲明順序或者存儲(chǔ)順序的行為與編譯器強(qiáng)相關(guān)
  • 所有其他方法(構(gòu)造函數(shù),析構(gòu)函數(shù)和編譯器擴(kuò)展代碼)都進(jìn)存儲(chǔ)在文本段。然后,這些方法將被調(diào)用并隱式地在調(diào)用對(duì)象的第一個(gè)參數(shù)中傳遞該指針。

this指針是一個(gè)隱含于每一個(gè)成員函數(shù)中的特殊指針。它是一個(gè)指向正在被該成員函數(shù)操作的對(duì)象,也就是要操作該成員函數(shù)的對(duì)象。this作用域是在類(lèi)內(nèi)部,當(dāng)對(duì)一個(gè)對(duì)象調(diào)用成員函數(shù)時(shí),編譯程序先將對(duì)象的地址賦給this指針,編譯器會(huì)自動(dòng)將對(duì)象本身的地址作為一個(gè)隱含參數(shù)傳遞給函數(shù)。也就是說(shuō),即使你沒(méi)有寫(xiě)this指針,編譯器在編譯的時(shí)候也是加上this的,它作為非靜態(tài)成員函數(shù)的隱含形參。被調(diào)用的成員函數(shù)函數(shù)體內(nèi)所有對(duì)類(lèi)成員的訪問(wèn),都會(huì)被轉(zhuǎn)化為“this->類(lèi)成員”的方式。

針對(duì)第二點(diǎn),我們類(lèi)似于:

A x;
x.printInt();

其中,X::printInt()這個(gè)行為,在編譯器中,將處理為

printInt(const X* this)

那么,x.printInt()調(diào)用處理將最終成為

printInt(&x);

同時(shí)具有虛函數(shù)和靜態(tài)數(shù)據(jù)成員的內(nèi)存布局

class X {
    int         x;
    float       xx;
    static int  count;

public:
    X() {}
    virtual ~X() {}

    virtual void printAll() {}
    void printInt() {}
    void printFloat() {}
    static void printCount() {}
};

其內(nèi)存布局如下

      |                        |          
      |------------------------| <------ X class object memory layout
      |        int X::x        |
stack |------------------------|
  |   |       float X::xx      |                      
  |   |------------------------|      |-------|--------------------------|
  |   |         X::_vptr       |------|       |       type_info X        |
 \|/  |------------------------|              |--------------------------|
      |           o            |              |    address of X::~X()    |
      |           o            |              |--------------------------|
      |           o            |              | address of X::printAll() |
      |                        |              |--------------------------|
      |                        |
------|------------------------|------------
      |  static int X::count   |      /|\
      |------------------------|       |
      |           o            |  data segment           
      |           o            |       |
      |                        |      \|/
------|------------------------|------------
      |        X::X()          | 
      |------------------------|       |   
      |        X::~X()         |       |
      |------------------------|       | 
      |      X::printAll()     |      \|/ 
      |------------------------|  text segment
      |      X::printInt()     |
      |------------------------|
      |     X::printFloat()    |
      |------------------------|
      | static X::printCount() |
      |------------------------|
      |                        |
  • 所有非靜態(tài)數(shù)據(jù)成員都按照聲明的順序?qū)⒖臻g放入堆棧中,與前面的示例順序相同。
  • 靜態(tài)數(shù)據(jù)成員將空間放入內(nèi)存的數(shù)據(jù)段中。使用范圍解析運(yùn)算符(即::)進(jìn)行的訪問(wèn)。但是在編譯之后,就沒(méi)有像作用域和名稱(chēng)空間那樣的東西了。因?yàn)?,它的名稱(chēng)只是由編譯器執(zhí)行,所以所有內(nèi)容都由其絕對(duì)或相對(duì)地址引用。
  • 靜態(tài)數(shù)據(jù)成員將空間放入內(nèi)存的數(shù)據(jù)段中。使用范圍解析運(yùn)算符(即::)進(jìn)行的訪問(wèn)。
  • 靜態(tài)方法進(jìn)入文本段,并通過(guò)作用域解析運(yùn)算符進(jìn)行調(diào)用。
  • 對(duì)于virtual關(guān)鍵字,編譯器會(huì)自動(dòng)將指向虛擬表的指針(vptr)插入對(duì)象內(nèi)存表示中。通常,虛擬表是在數(shù)據(jù)段中為每個(gè)類(lèi)靜態(tài)創(chuàng)建的,但它也取決于編譯器的實(shí)現(xiàn)。
  • 在虛擬表中,第一個(gè)條目指向type_info對(duì)象,該對(duì)象包含與當(dāng)前基類(lèi)和其他基類(lèi)的DAG(有向無(wú)環(huán)圖)相關(guān)的信息(如果從這些基類(lèi)派生的信息)。

繼承對(duì)象的內(nèi)存布局

class X {
    int     x;
    string str;

public:
    X() {}
    virtual ~X() {}

    virtual void printAll() {}
};

class Y : public X {
    int     y;

public:
    Y() {}
    ~Y() {}

    void printAll() {}
};

其內(nèi)存布局信息如下

      |                              |          
      |------------------------------| <------ Y class object memory layout
      |          int X::x            |
stack |------------------------------|
  |   |              int string::len |
  |   |string X::str ----------------|
  |   |            char* string::str |         
 \|/  |------------------------------|      |-------|--------------------------|
      |           X::_vptr           |------|       |       type_info Y        |
      |------------------------------|              |--------------------------|
      |          int Y::y            |              |    address of Y::~Y()    |
      |------------------------------|              |--------------------------|
      |               o              |              | address of Y::printAll() |
      |               o              |              |--------------------------|
      |               o              |              
------|------------------------------|--------
      |           X::X()             | 
      |------------------------------|       |   
      |           X::~X()            |       |
      |------------------------------|       | 
      |         X::printAll()        |      \|/ 
      |------------------------------|  text segment
      |           Y::Y()             |
      |------------------------------|
      |           Y::~Y()            |
      |------------------------------|
      |         Y::printAll()        |
      |------------------------------|
      |      string::string()        |
      |------------------------------|
      |      string::~string()       |
      |------------------------------|
      |      string::length()        |
      |------------------------------|
      |               o              |
      |               o              |
      |               o              |
      |                              |
  • 在繼承模型中,基類(lèi)和數(shù)據(jù)成員類(lèi)是派生類(lèi)的子對(duì)象。
  • 編譯器會(huì)在類(lèi)的構(gòu)造函數(shù)中生成具有所有重寫(xiě)的虛擬功能和為_(kāi)vptr分配虛擬表的代碼的虛擬表。

具有多重繼承和虛擬功能的對(duì)象的內(nèi)存布局

class X {
public:
    int     x;
    
    virtual ~X() {}
    virtual void printX() {}
};

class Y {
public:
    int     y;
    
    virtual ~Y() {}
    virtual void printY() {}
};

class Z : public X, public Y {
public:
    int     z;
    
    ~Z() {}
    void printX() {}
    void printY() {}
    void printZ() {}
};

內(nèi)存布局如下

      |                              |          
      |------------------------------| <------ Z class object memory layout
stack |          int X::x            |         
  |   |------------------------------|                  |--------------------------|      
  |   |          X:: _vptr           |----------------->|       type_info Z        |
  |   |------------------------------|                  |--------------------------|
 \|/  |          int Y::y            |                  |    address of Z::~Z()    |
      |------------------------------|                  |--------------------------|
      |          Y:: _vptr           |------|           |   address of Z::printX() |
      |------------------------------|      |           |--------------------------|
      |          int Z::z            |      |           |--------GUARD_AREA--------|    
      |------------------------------|      |           |--------------------------|
      |              o               |      |---------->|       type_info Z        |
      |              o               |                  |--------------------------|
      |              o               |                  |    address of Z::~Z()    |
      |                              |                  |--------------------------|
------|------------------------------|---------         |   address of Z::printY() |
      |           X::~X()            |       |          |--------------------------|  
      |------------------------------|       |          
      |          X::printX()         |       |        
      |------------------------------|       |         
      |           Y::~Y()            |      \|/        
      |------------------------------|  text segment
      |          Y::printY()         |                
      |------------------------------|                
      |           Z::~Z()            |                
      |------------------------------|                
      |          Z::printX()         |                
      |------------------------------|                
      |          Z::printY()         |                
      |------------------------------|                
      |          Z::printZ()         |                
      |------------------------------|                
      |               o              |                
      |               o              |                
      |                              |               

在多繼承層次結(jié)構(gòu)中,創(chuàng)建的虛擬表指針(vptr)的確切數(shù)目將為N-1,其中N代表類(lèi)的數(shù)目。

如果嘗試使用任何基類(lèi)指針調(diào)用Z類(lèi)的方法,則它將使用相應(yīng)的虛擬表進(jìn)行調(diào)用。如下例子所示:

Y *y_ptr = new Z;
y_ptr->printY(); // OK
y_ptr->printZ(); // Not OK, as virtual table of class Y doesn't have address of printZ() method

在上面的代碼中,y_ptr將指向完整Z對(duì)象內(nèi)類(lèi)Y的子對(duì)象。

結(jié)果,調(diào)用任何方法,例如使用y_ptr-> printY()。 使用y_ptr的解析方式如下:

 ( *y_ptr->_vtbl[ 2 ] )( y_ptr )

虛繼承內(nèi)存布局

class X { int x; };
class Y : public virtual X { int y; };
class Z : public virtual X { int z; };
class A : public Y, public Z { int a; };

其布局如下:

                  |                |          
 Y class  ------> |----------------| <------ A class object memory layout
sub-object        |   Y::y         |          
                  |----------------|             |------------------| 
                  |   Y::_vptr_Y   |------|      |    offset of X   | // offset(20) starts from Y 
 Z class  ------> |----------------|      |----> |------------------|     
sub-object        |   Z::z         |             |       .....      |     
                  |----------------|             |------------------|  
                  |   Z::_vptr_Z   |------|       
                  |----------------|      |        
 A sub-object --> |   A::a         |      |      |------------------| 
                  |----------------|      |      |    offset of X   | // offset(12) starts from Z
 X class -------> |   X::x         |      |----> |------------------|          
 shared           |----------------|             |       .....      |           
 sub-object       |                |             |------------------|           
  • 具有一個(gè)或多個(gè)虛擬基類(lèi)的派生類(lèi)的內(nèi)存表示形式分為兩個(gè)區(qū)域:不變區(qū)域和共享區(qū)域。
  • 不變區(qū)域內(nèi)的數(shù)據(jù)與對(duì)象的起始位置保持固定的偏移量,而與后續(xù)派生無(wú)關(guān)。
  • 共享區(qū)域包含虛擬基類(lèi),并且隨后續(xù)派生和派生順序而波動(dòng)。

總結(jié)

了解內(nèi)存布局,對(duì)我們的項(xiàng)目開(kāi)發(fā)會(huì)提供很大的便利,比如對(duì)coredump的調(diào)試

到此這篇關(guān)于c++對(duì)象內(nèi)存布局的文章就介紹到這了,更多相關(guān)c++對(duì)象內(nèi)存布局內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++鎖機(jī)制與信號(hào)機(jī)制對(duì)比分析

    C++鎖機(jī)制與信號(hào)機(jī)制對(duì)比分析

    文章介紹C++多線(xiàn)程編程中線(xiàn)程同步與通信的鎖機(jī)制(互斥鎖、讀寫(xiě)鎖及RAII封裝)和信號(hào)機(jī)制(條件變量、信號(hào)量),并對(duì)比其在資源控制、并發(fā)限制和線(xiàn)程協(xié)調(diào)中的應(yīng)用場(chǎng)景與優(yōu)缺點(diǎn),對(duì)C++鎖機(jī)制與信號(hào)機(jī)制相關(guān)知識(shí)感興趣的朋友一起看看吧
    2025-06-06
  • C語(yǔ)言選擇、循環(huán)、函數(shù)、數(shù)組與操作符

    C語(yǔ)言選擇、循環(huán)、函數(shù)、數(shù)組與操作符

    這篇文章主要介紹了C語(yǔ)言選擇、循環(huán)、函數(shù)、數(shù)組與操作符,文章基于C語(yǔ)言展開(kāi)對(duì)主題的詳細(xì)介紹,下文內(nèi)容需要的小伙伴可以參考一下
    2022-04-04
  • C++使用new和delete進(jìn)行動(dòng)態(tài)內(nèi)存分配與數(shù)組封裝

    C++使用new和delete進(jìn)行動(dòng)態(tài)內(nèi)存分配與數(shù)組封裝

    這篇文章主要介紹了C++使用new和delete進(jìn)行動(dòng)態(tài)內(nèi)存分配與數(shù)組封裝,運(yùn)行期間才能確定所需內(nèi)存大小,此時(shí)應(yīng)該使用new申請(qǐng)內(nèi)存,下面我們就進(jìn)入文章學(xué)習(xí)具體的操作方法,需要的小伙伴可以參考一下
    2022-03-03
  • C語(yǔ)言單值二叉樹(shù)真題講解

    C語(yǔ)言單值二叉樹(shù)真題講解

    單值二叉樹(shù)你可能之前沒(méi)見(jiàn)過(guò),如果二叉樹(shù)每個(gè)節(jié)點(diǎn)都具有相同的值,那么該二叉樹(shù)就是單值二叉樹(shù),讓我們通過(guò)一個(gè)真題來(lái)深刻了解它吧
    2022-04-04
  • C++的靜態(tài)成員變量和靜態(tài)成員函數(shù)詳解

    C++的靜態(tài)成員變量和靜態(tài)成員函數(shù)詳解

    這篇文章主要為大家介紹了C++的靜態(tài)成員變量和靜態(tài)成員函數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2021-12-12
  • C++之Boost::array用法簡(jiǎn)介

    C++之Boost::array用法簡(jiǎn)介

    這篇文章主要介紹了C++之Boost::array用法簡(jiǎn)介,較為詳細(xì)的分析了Boost::array中的常見(jiàn)用法,并用實(shí)例的形式予以總結(jié)歸納,需要的朋友可以參考下
    2014-10-10
  • 使用C++實(shí)現(xiàn)順序鏈表

    使用C++實(shí)現(xiàn)順序鏈表

    今天小編就為大家分享一篇關(guān)于使用C++實(shí)現(xiàn)順序鏈表,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • vscode配置gitbash終端的方法步驟

    vscode配置gitbash終端的方法步驟

    本文主要介紹了vscode配置gitbash終端的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 淺析C++ new的三種面貌

    淺析C++ new的三種面貌

    這篇文章主要介紹了C++ new的三種面貌,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下
    2020-08-08
  • 淺析C++中模板的那點(diǎn)事

    淺析C++中模板的那點(diǎn)事

    C++中的模板可分為函數(shù)模板和類(lèi)模板,而把函數(shù)模板的具體化稱(chēng)為模板函數(shù),把類(lèi)模板的具體化成為模板類(lèi)。下面讓我們分別看看什么是函數(shù)模板和類(lèi)模板吧
    2013-09-09

最新評(píng)論

营山县| 竹溪县| 荃湾区| 崇文区| 延吉市| 灌云县| 辽阳县| 富川| 福海县| 资阳市| 资源县| 淮阳县| 建瓯市| 永泰县| 平阳县| 江都市| 屏边| 什邡市| 长海县| 古蔺县| 江阴市| 景洪市| 洪江市| 广平县| 十堰市| 卓尼县| 周宁县| 贡觉县| 辽中县| 开封市| 同心县| 明水县| 威信县| 上饶县| 韩城市| 宁化县| 罗山县| 萨嘎县| 商洛市| 辽宁省| 南江县|