C 程式執行時記憶體布局之this到底是什麼?

2021-08-26 00:01:25 字數 2516 閱讀 7449

先問乙個問題,在c++裡,成員函式裡的this指標和呼叫此函式的物件位址總是一樣的嗎?如果你的回答是:不一定。那麼至少你是個老手吧,下面的內容你就不用看了;如果你的回答是:是啊,那麼強烈建議你看看下面的內容。

非靜態成員函式,無論是不是虛函式,都隱藏了乙個this指標引數。這個引數的目的就是給函式提供乙個基位址,以便於函式體內能找到物件的成員變數。那非靜態成員函式是如何根據this指標找到成員變數的呢?直接看例子吧

1沒有虛表的情況

view plain

copy to clipboard

print?

#include

#include

using

namespacestd;

classa

};intmain(intargc,char**argv)

#include #include using namespace std;class a

那麼函式f1的實現偽**為:

*(this+&a::x-1) = 1;

*(this+&a::y-1) = 2;

其中&a::x是成員x的偏移+1,&a::y是成員y的偏移+1,這可是c++基本語法的知識,希望你知道,呵呵。可這些偏移量是相對應那裡的偏移呢,是物件位址嗎,答案是no。是相對於第乙個成員變數的偏移,這對於有些物件也許沒有差別,但是對於有虛表的類的物件,就有差別了。這些偏移在編譯期間就是確定了的。對於本例在vc++2010下&a::x,值為1, &a::y,值為5。為什麼不是0,4,請看《inside the c++ object model》。

所以,對於找到成員變數,需要進一步確定的只有this的值。程式執行結果如下:

可見此例中,物件的位址與this指標的位址相同,記憶體圖如下所示。

2有乙個虛表的情況

view plain

copy to clipboard

print?

#include

#include

using

namespacestd;

classa

};intmain(intargc,char**argv)

#include #include using namespace std;class a

此時函式f1的實現偽**為:

*(this+4+&a::x-1) = 1; //+4是因為存在虛表指標

*(this+4+&a::y-1) = 2; //+4是因為存在虛表指標

程式執行結果如下:

記憶體布局如下:

3單繼承的情況

view plain

copy to clipboard

print?

#include

#include

using

namespacestd;

classa

};classb:publica

};intmain(intargc,char**argv)

#include #include using namespace std;class a

執行結果:

記憶體布局:

4 多繼承的情況

先看a沒有虛函式,b有虛函式的情況

view plain

copy to clipboard

print?

#include

#include

using

namespacestd;

classa

};classb

};classc:publica,publicb

voidf3()

};intmain(intargc,char**argv)

#include #include using namespace std;class a

結果:記憶體布局:

再看,如果a,b都有虛函式的情況。

**:view plain

copy to clipboard

print?

#include

#include

using

namespacestd;

classa

};classb

};classc:publica,publicb

voidf3()

};intmain(intargc,char**argv)

#include #include using namespace std;class a

結果:記憶體布局:

結論:再一次驗證了this指標的值的確定方法,this始終要保證指向定義了該成員函式的類得subobject。因為c++保證base class subobject與base class object完全對應,從而保證了成員函式能根據成員變數在定義了該變數的類中的偏移定址。

程式執行時的記憶體

當乙個源 通過gcc編譯成a.out,執行a.out時 程式便開始了執行之旅 即程序 作業系統為程序分配堆疊空間,隨後把程式執行碼放入文字段,把程式經過初始化的全域性變數和靜態變數放入data 把程式為初始化的全域性變數和靜態變數放入bss段 並對bss段資料初始化為0 之後cpu 段指標指向mai...

程式執行時記憶體管理

1,管理執行階段記憶體空間分配 malloc new int pn new int 儲存的型別,記憶體根據此設定相應儲存位元組的記憶體 pn是記憶體位址 所以 當宣告乙個變數的指標變數時沒初始化,宣告後再來初始化則pn 接收的應該是變數在記憶體中的位址 variablename pn是儲存在記憶體的...

c 程式執行時的記憶體分配

c 中,記憶體分為5個區 堆 棧 自由儲存區 全域性 靜態儲存區和常量儲存區。1 棧 是由編譯器在需要時自動分配,不需要時自動清除的變數儲存區。通常存放區域性變數 函式引數等。2 堆 是由new分配的記憶體塊,由程式設計師釋放 編譯器不管 一般乙個new與乙個delete對應,乙個new與乙個del...