美文网首页程序员C++
C++ 对象和内存

C++ 对象和内存

作者: DayDayUpppppp | 来源:发表于2017-04-26 12:40 被阅读0次
    一个类创建的对象所占据的内存空间是多少?
    1. 非静态的数据成员的总和大小
    2. 边界对齐(操作系统会根据计算机的位数,将数据按照字长来对齐)
    3. 为了支持virtual机制,而产生的额外负担

    Q1:一个空类的大小是多少?
    class empty_class {
    };
    
    int main() {
        empty_class e;
          //输出的结果是1
        cout << sizeof(e) << endl;
    }
    

    输出的结果是1;
    A1:也就是说一个空类的大小是1。

    Q2:如何分析一个正常的类的大小?
    class test_class {
    private:
        int val;
    };
    
    int main(){
        test_class t;
         //输出4
        cout << sizeof(t) << endl;
    }
    

    输出的结果是4,也就是说对象的大小是对象里面的数据成员的大小。

    class test_class {
    public:
        void fun2() {
            cout << "func2" << endl;
        }
    
        void fun3() {
            cout << "func3" << endl;
        }
    
        void fun1() {
            cout << "func1" << endl;
        }
    };
    
    int main(){
        test_class t;
        //输出是1,因为没有数据成员,都是成员函数,但是成员函数是不占据空间的
        cout << sizeof(t) << endl;
    }
    

    输出是1,因为没有数据成员,都是成员函数,但是成员函数是不占据空间的


    Q3:如何分析一个继承类的对象的大小?
    class Animal {
    private:
        int loc;
        int id;
    public:
        void getid() {
            cout << id << endl;
        }
    
        void getloc() {
            cout << loc << endl;
        }
    
        void print() {
            cout << loc << endl;
            cout << id << endl;
        }
    };
    
    class Bear : public Animal {
    private:
        char name[8];
        int age;
    
    public:
        void getage() {
            cout << age << endl;
        }
    };
    
    int main(){
        Animal a;
        //a 里面有两个int的数据成员,大小是4*2
        cout << sizeof(a) << endl;
    
        Bear b;
        //基类对象的大小是8+ 派生类里面的大小 8*1+4 ,也就是8+8+4=20
        cout << sizeof(b) << endl;
    }
    
    Q4:一个带有虚函数的类的大小
    class myclass {
    public:
        int val;
        virtual void print() {
            cout << "123" << endl;
        }
    };
    
    int main() {
        myclass m;
        // 输出的结果是8
        cout << sizeof(m) << endl;
    }
    

    注意这里输出的结果是8,为什么是8呢? 是因为如果一个类包含了虚函数,那么创建对象的时候,对象里面就会多一个虚函数的指针,所以是8。但是如果去掉了virtual,输出的结果就是4了。

    这个其实告诉我们很重要的一点:
    对于一个类创建的对象,这个对象里面保存的不仅仅是数据成员,还有一个就是虚函数指针。

    所以,在构造函数,拷贝构造函数,赋值构造函数等等,都需要考虑这个虚指针的情况。

    Q5:体现内存对齐的
    class char_class {
    public:
        char c[1];
        int val;
    };
    
    char_class ss;
    //输出的结果是 8
    cout<<sizeof(ss)<<endl;
    
    但是
    class char_class {
    public:
        char c[1];
    };
    char_class ss;
    //输出的结果是 1
    cout<<sizeof(ss)<<endl;
    

    这两个不同的输出,体现了内存对齐的原则。


    对于有virtual的class的对象的分析

    对于有virtual的class,每个对象里面还会有一个vptr(虚指针) 4个字节。

    #include <iostream>
    #include <typeinfo>
    using namespace std;
    
    typedef void(*Fun)(void);  //函数指针
    // //关于为什么要这样写:https://www.cnblogs.com/windlaughing/archive/2013/04/10/3012012.html
    
    class Parent 
    {
    public:
        int iparent;
        Parent() :iparent(10) {}
        virtual void f() { cout << " Parent::f()" << endl; }
        virtual void g() { cout << " Parent::g()" << endl; }
        virtual void h() { cout << " Parent::h()" << endl; }
    };
    
    
    class Child : public Parent 
    {
    public:
        int ichild;
        Child() :ichild(100) {}
        virtual void f() { cout << "Child::f()" << endl; }
        virtual void g_child() { cout << "Child::g_child()" << endl; }
        virtual void h_child() { cout << "Child::h_child()" << endl; }
    };
    
    class GrandChild : public Child 
    {
    public:
        int igrandchild;
        GrandChild() :igrandchild(1000) {}
        virtual void f() { cout << "GrandChild::f()" << endl; }
        virtual void g_child() { cout << "GrandChild::g_child()" << endl; }
        virtual void h_grandchild() { cout << "GrandChild::h_grandchild()" << endl; }
    };
    
    int main()
    {
        Fun pFun = NULL;
        GrandChild gc;
    
        int** pVtab = (int**)&gc;
        cout << "[0] GrandChild::_vptr->" << endl;
        for (int i = 0; pVtab[0][i] != NULL; i++) 
        {
            pFun = (Fun)pVtab[0][i];
            cout << "    [" << i << "] ";
            pFun();
        }
        cout << "[1] Parent.iparent = " << (int)pVtab[1] << endl;
        cout << "[2] Child.ichild = " << (int)pVtab[2] << endl;
        cout << "[3] GrandChild.igrandchild = " << (int)pVtab[3] << endl;
    
        return 0;
    }
    

    这个对象的内存布局,如下:


    这个就是这个对象的内存布局.png

    相关文章

      网友评论

        本文标题:C++ 对象和内存

        本文链接:https://www.haomeiwen.com/subject/wdeizttx.html