C++ 类生成对象时内存的结构

一个类中都有什么元素呢?

成员变量、成员函数。

成员变量又分普通的成员变量、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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章