對於c++開發者來說,了解其記憶體是非常必要的,同時c++的多型(動態繫結)的原理也是很重要的。
c++記憶體布局:
需要了解的幾種情況:
1、無虛函式,非繼承;
class ****** ;
void ******_fun2() {};
private:
int ******_a_;
};
記憶體布局:
沒有虛函式,沒有繼承,所以只有成員變數需要分配空間。
2、有虛函式,非繼承;
class base
virtual void func2()
virtual void func3()
private:
int a_;
};
記憶體布局以及虛函式列表:
沒有繼承,有虛函式,所以有了虛函式列表vfptr,指向該類的虛函式列表,虛函式列表中記錄當前類的虛函式;
3、無虛函式,繼承;
class ******1 : public ****** ;
private:
int ******1_a_;
};
記憶體布局:
普通的繼承關係,而且基類中沒有虛函式,所以不會生成虛函式列表,指向基類的和指向自身類的指標是同乙個。
4、有虛函式,單繼承;
class derived : public base
virtual void func4()
private:
int b_;
};
記憶體布局以及虛函式和列表:
單繼承中,基類有虛函式,所以首先是虛函式列表,然後是從基類繼承過來的成員變數,最後才是自己的成員變數。
由於override了基類的func2(),所以在虛函式列表中可以開看到,func2的域是derived,而不再是基類base。
5、有虛函式,多繼承(非虛擬繼承);
class derived2 : public base
virtual void func5()
private:
int c_;
};class derived3 : public derived, public derived2
private:
int d_;
};
記憶體布局:
從以上記憶體布局可以發現一些問題,就是屬於base的成員變數a_出現了兩次,雖然生成的時候可以通過,但是在實際使用過程中容易造成二義性出錯,所以這種用法是需要盡量避免的。
虛函式列表:
虛函式列表中也有同樣的問題,兩個虛函式列表,有重複的函式base::func3(),在實際中也要盡量避免。
6、無虛函式,多繼承,虛擬繼承;
將以上的derived類和derived2類對base的繼承改為虛擬繼承:
class derived3 : public derived, public derived2
private:
int d_;
};
記憶體布局:
最後一種情況使用了虛擬繼承,記憶體布局就不同了,可以看出,一共有5個虛函式列表,在第一部分中(0~8),由兩個虛函式列表和derived的成員變數b_,第乙個虛函式列表是derived3類繼承derived類時生成的,第二個虛函式是derived繼承時base生成的。
對於第二部分(12~20)同理,第三部分(24)則是derived3自己的成員變數;
第四部分(28~32),則是derived3間接繼承base生成的。
虛函式列表:
虛函式列表有點複雜,此處有點不明白,為什麼會有負數出現,隱約能夠看懂虛函式列表的指向。
從以上可以看到,在例項化乙個類物件的時候,僅僅為類的成員變數和虛函式列表指標分配空間(虛函式的情況下),而成員函式屬於整個類共有的,不會再物件中分配空間。因此,當虛函式更多的時候,占用的記憶體空間會更多,所以在實際專案中,關於類的繼承體系的設計,需要考慮到這個方面。
如有問題,還請指正。
C 記憶體洩漏的幾種情況
1.在類的建構函式和析構函式中沒有匹配的呼叫new和delete函式 兩種情況下會出現這種記憶體洩露 一是在堆裡建立了物件占用了記憶體,但是沒有顯示地釋放物件占用的記憶體 二是在類的建構函式中動態的分配了記憶體,但是在析構函式中沒有釋放記憶體或者沒有正確的釋放記憶體 2.沒有正確地清除巢狀的物件指標...
c 類的記憶體布局
本文基本上是對於stanley b.lippman的inside the c object model一書第一章第三章的概括,描述了c 類的記憶體布局情況.c 的類的記憶體布局有如下規則 1.nonstatic data member 存放在class object中 2.static data m...
c 類的記憶體布局
c 中的struct需要記憶體對齊,便於機器訪問該struct。每個物件 如果類含有虛函式 在首位址位置放置了vptr,指向自己的虛函式表。物件中不包含成員函式 靜態的或非靜態的 它們可以被物件共享,靜態成員函式沒有this指標,所以不能被物件呼叫,non static 成員函式隱含有乙個this指...