from: here
1.虛函數表是全局共享的元素,即全局僅有一個.
2.虛函數表類似一個數組,類對象中存儲vptr指針,指向虛函數表.即虛函數表不是函數,不是程序代碼,不肯能存儲在代碼段.
3.虛函數表存儲虛函數的地址,即虛函數表的元素是指向類成員函數的指針,而類中虛函數的個數在編譯時期可以確定,即虛函數表的大小可以確定,即大小是在編譯時期確定的,不必動態分配內存空間存儲虛函數表,所以不再堆中.
根據以上特征,虛函數表類似於類中靜態成員變量.靜態成員變量也是全局共享,大小確定.
所以我推測虛函數表和靜態成員變量一樣,存放在全局數據區.
c/c++程序所占用的內存一共分為五種:
棧區,堆區,程序代碼區,全局數據區(靜態區),文字常量區.
顯而易見,虛函數表存放在全局數據區.
幾個值得注意的問題
- 虛函數表是class specific的,也就是針對一個類來說的,這里有點像一個類里面的staic成員變量,即它是屬於一個類所有對象的,不是屬於某一個對象特有的,是一個類所有對象共有的。
- 虛函數表是編譯器來選擇實現的,編譯器的種類不同,可能實現方式不一樣,就像前面我們說的vptr在一個對象的最前面,但是也有其他實現方式,不過目前gcc 和微軟的編譯器都是將vptr放在對象內存布局的最前面。
- 雖然我們知道vptr指向虛函數表,那么虛函數表具體存放在內存哪個位置呢,雖然這里我們已經可以得到虛函數表的地址。實際上虛函數指針是在構造函數執行時初始化的,而虛函數表是存放在可執行文件中的。下面的一篇博客測試了微軟的編譯器將虛函數表存放在了目標文件或者可執行文件的常量段中,http://blog.csdn.net/vicness/article/details/3962767,不過我在gcc下的匯編文件中沒有找到vtbl的具體存放位置,主要是對可執行文件的裝載和運行原理還沒有深刻的理解,相信不久有了這些知識之后會很輕松的找到虛函數表到底存放在目標文件的哪一個段中。
- 經過測試,在gcc編譯器的實現中虛函數表vtable存放在可執行文件的只讀數據段.rodata中。
虛函數表vtable在Linux/Unix中存放在可執行文件的只讀數據段中(rodata),這與微軟的編譯器將虛函數表存放在常量段存在一些差別。