一個類中都有什麼元素呢?
成員變量、成員函數。
成員變量又分普通的成員變量、static靜態成員變量、const常量
成員函數分爲普通成員函數、靜態成員函數、虛函數、純虛函數等
那麼他們分別又是如何在類的內存中分配的呢?
1.內存對齊原則
不論是在類中還是在結構體中,都需要內存對齊,具體對齊方式(有一個對齊係數——可以自己定義,同常是2、4或4的倍數,不是對齊係數倍數的元素會擴展到對齊係數的倍數上,整體的內存大小也是對齊係數的整數倍)。
2.空類
作爲空類在內存中編譯器會自動爲該類申請一字節的內存空間,方便在代碼區存儲這個類。
3.成員變量在內存中的存儲方式
順序存貯!在內存中,不論類中的普通變量(即存在棧中的變量)是私有類型還是共有類型、保護類型,在內存中的存貯方式都是順序存儲結構,const(常量)類型在內存中依舊是順序結構。但是靜態變量由於要在主函數外部、類外部進行變量的再次空間賦值聲明,導致並沒有存在類裏的同一塊棧空間裏,而是另一塊的棧空間,所以他們之間的內存空間是不連續的。
4.成員函數在內存中的存儲方式
作爲一個類的成員函數,這些成員函數在編譯的時候就已經放到了代碼區,在運行時再分配內存。同一個類的所有對象共享同一段代碼區內存的成員函數,相當於對象只實例化其中變量的地址,並沒有實例化函數,函數是一直存在哪裏的。不論是普通成員函數還是靜態了、常量啦、虛函數啦、純虛函數就不一樣了!在內存中都是鏈式結構存儲的。(也有可能有什麼規律但是在我輸出內存看的時候並沒有發現)
#include <iostream>
#include <cstdio>
using namespace std;
// 可以看到空類編譯時也會分配一個字節內存,隱含添加內存
class A {
};
// 類中的成員變量內存分佈像結構體一樣,有內存對齊,並且是連續分配內存空間的
class B {
public:
int a;
int b;
char c;
};
// 不過其中的char類型成員變量我就沒有看懂了
class C {
public:
char a; // char 類型成員變量非常的奇怪
};
class D {
public:
int a;
int b;
void func1 () {}
void func2 () {
int i;
}
virtual void func3 () {
cout << "virtual" << endl;
}
};
class ownerShip {
private:
int a;
int b;
public:
int c;
ownerShip () {
}
void coutAddress () {
cout << "ownerShip a address is : " << &a << endl;
cout << "ownerShip b address is : " << &b << endl;
cout << "ownerShip c address is : " << &c << endl;
// 要注意此處有兩種寫法,一是通過全局的類名字方式訪問成員函數,另一種是通過this指針傳遞過來的類內部
printf ("ownerShip coutAddress is : %p \n", (void *)&ownerShip::coutAddress);
printf ("ownerShip coutAddress is : %p \n", (void *)&this->coutAddress);
printf ("ownerShip func address is : %p \n", (void * ) &this->func);
printf ("ownerShip func1 address is : %p \n", (void *) &this->func1); // 虛函數
//printf ("ownerShip func2 address is : %p \n", (void *) &this->func2); // 純虛函數
printf ("ownerShip func3 address is : %p \n", (void *) &this->func3); // 靜態函數
}
// 成員函數有一個指向自己類的指針,意味着成員函數可以通過調用this指針調用這個函數自身
void func () {
}
virtual void func1 () {
cout << 1 << endl;
}
//virtual void func2 () = 0;
static void func3 () {
cout << 2 << endl;
}
const void func4 () {
cout << 3 << endl;
}
const static func5 () {
cout << "fuck" << endl;
}
static const func6 () {
cout << "fuck!!" << endl;
}
};
/*
class sub_for_virtual : public ownerShip{
public:
void func2 () {
cout << "sub virtual" << endl;
}
};
/**/
class verifyVar {
private:
int a;
double b;
static int e;
static int g;
const int j = 1;
public:
float c;
bool d;
static int f;
static int h;
const int i = 2;
void func () {
// 順序結構
cout << "verify a address is : " << &a << endl;
cout << "verify b address is : " << &b << endl;
cout << "verify j address is : " << &j << endl;
cout << "verify c address is : " << &c << endl;
//cout << &e << endl;
//cout << &f << endl;
cout << "verify d address is : " << &d << endl;
cout << "verify i address is : " << &i << endl;
printf ("%p\n", (void*)&this->func);
}
};
class funcStorage {
public:
int func () {}
virtual void func1 () {}
static func2 () {}
const func3 () {}
void cout_ () {
cout << endl;
printf ("func is : %p\n", (void*)&this->func);
printf ("func1 is : %p\n", (void*)&this->func1);
printf ("func2 is : %p\n", (void*)&this->func2);
printf ("func3 is : %p\n", (void*)&this->func3);
}
};
int e = 0;
int f = 1;
int g = 2;
int h = 3;
int main ()
{
A a;
cout << sizeof (A) << endl;
cout << sizeof (a) << endl;
B b;
cout << sizeof (B) << endl;
cout << sizeof (b) << endl;
cout << "B address : " << &b << endl;
cout << "B->a address : " << &(b.a) << endl;
cout << "B->b address : " << &(b.b) << endl;
cout << "B->c address : " << &(b.c) << endl;
C c;
cout << "C address : " << &c << endl;
cout << "C->a address : " << &(c.a) << endl;
D d;
cout << "D size is : " << sizeof (D) << endl;
cout << "D address is : " << &d << endl;
cout << "D->b address is : " << &d.b << endl;
//cout << "D->func1 address is : " << (int*)&D::func1 << endl;
printf ("D->func1 address is : %p \n", (void *)&d.func1);
printf ("D->func2 address is : %p \n", (void *)&d.func2);
printf ("D->func3 address is : %p \n", (void *)&d.func3);
D _d;
cout << "_D->b address is : " << &_d.b << endl; // 可以見得不同對象之間的成員變量存儲在不同的內存空間,但是同一個類的成員函數卻不一樣,都存在同一段代碼段中。
//sub_for_virtual sub;
ownerShip *ownership = new ownerShip ();
ownership->coutAddress();
verifyVar verifyvar;
verifyvar.func ();
// 很奇怪的存儲方式,不是順序結構,可能是鏈式結構
cout << &e << endl;
cout << &g << endl;
cout << &f << endl;
cout << &h << endl;
//cout << "????";
funcStorage funcstorage ;
funcstorage.cout_();
cout << endl;
return 0;
}