zoukankan      html  css  js  c++  java
  • 类和对象(11)—— 编译器对属性和方法的处理机制

    1、静态成员占多大?

    一个空的class在内存中多少字节?如果加入一个成员函数后是多大?这个成员函数存储在内存中什么部分?

    一个Class对象需要占用多大的内存空间。最权威的结论是: 

    • 非静态成员变量总合。
    • 加上编译器为了CPU计算,作出的数据对齐处理。 
    • 加上为了支持虚函数,产生的额外负担。

    (1)空类的Size

    class Car
    {
    };
    
    void main()
    {
       Car objCar; cout
    << sizeof(objCar) << endl;//1 }

    编译器在执行Car objCar;这行代码后需要,作出一个Class Car的Object。并且这个Object的地址还是独一无二的,于是编译器就会给空类创建一个隐含的一个字节的空间。

    (2)只有成员变量的Size

    class Car
    {
    private:
        int nLength;
        int nWidth;
    };
    
    void main()
    {
        cout << sizeof(Car) << endl;//8
    }

    在32位系统中,整型变量占4个字节。这里Class Car中含有两个整型类型的成员变量,所以Class Size是8。

    class Car
    {
    private:
        int nLength;
        int nWidth;
        static int sHigh;
    };
    
    void main()
    {
        Car objCar;
        cout << sizeof(objCar) << endl;//8

    我们这次在Class Car中添加了一个静态成员变量,但是Class Size仍然是8个字节。这正好符合了,结论中的第一条:非静态成员变量总合。

    class Car
    {
    private:
        char chLogo;
        int nLength;
        int nWidth;
        static int sHigh;
    };
    
    void main()
    {
        Car objCar;
        cout << sizeof(objCar) << endl;//12
    }

    在类中又插入了一个字符型变量,结果Class Size变成了12。这个就是编译器额外添加3个字符变量,做数据对齐处理,为了是提高CPU的计算速度。编译器额外添加的东西我们是无法看见的。这也符合了结论中的第二条:加上编译器为了CPU计算,作出的数据对齐处理。 
    既然,我们这样定义类成员数据编译器会额外的增加空。那么,我们何不在定义类的时候就考虑到数据对齐的问题,可以多定义出3个字符类型变量作为预留变量,既能满足数据对齐的要求,也给自己的程序添加了一些可扩展的空间。

    (3)只有成员函数的Size

    class Car
    {
    public:
        Car() {};
        ~Car() {};
    
        void Fun() {};
    };
    
    void main()
    {
        Car objCar;
        cout << sizeof(objCar) << endl;//1
    }

    噢,这是怎么回事儿呢?再做一个实验看看。

    class Car
    {
    public:
        Car() {};
        ~Car() {};
    
        void Fun() {};
    private:
        int nLength;
        int nWidth;
    };
    
    void main()
    {
        Car objCar;
        cout << sizeof(objCar) << endl;//8

    这次应该很清楚的了。函数是不占用类空间的。第一个例子中的Size为1个字节,正是编译器为类创建一个隐含的一个字节的空间。

    class Car
    {
    public:
        Car() {};
        virtual ~Car() {};
    
        void Fun() {};
    };
    
    void main()
    {
        Car objCar;
        cout << sizeof(objCar) << endl;//4
    }

    这次,让析构函数为虚函数,看到了Class Size为4。这正是指向Virtual Table的指针vptr的Size。这正好符合了,结论中的第三条:加上为了支持虚函数,产生的额外负担。

    #include <iostream>
    using namespace std;
    
    class C1
    {
    public:
        int i;//4
        int j;//4
        char k;//4
    };//12
    
    class C2
    {
    public:
        int i;//4
        int j;//4
        char k;//4
        static int m;
    
        int getK() const
        {
            return k;
        }
        void setK(int val)
        {
            k = val;
        }
    };
    
    struct S1
    {
        int i;//4
        int j;//4
        char k;//4
    };//12
    
    struct S2
    {
        int i;//4
        int j;//4
        char k;//4
        static int m;
    };//12
    
    int main()
    {
        cout << "C1:" << sizeof(C1) << endl;
        cout << "C2:" << sizeof(C2) << endl;
        cout << "S1:" << sizeof(S1) << endl;
        cout << "S2:" << sizeof(S2) << endl;
    
        return 0;
    }

    2、处理机制

    通过上面的案例,我们可以的得出:  

      C++类对象中的成员变量和成员函数是分开存储的。

    成员变量:
      普通成员变量:存储于对象中,与struct变量有相同的内存布局和字节对齐方式;
      静态成员变量:存储于全局数据区中;
    成员函数:存储于代码段中。

    1、C++类对象中的成员变量和成员函数是分开存储的。C语言中的内存四区模
    型仍然有效!
    2、C++中类的普通成员函数都隐式包含一个指向当前对象的this指针。
    3、静态成员函数、成员变量属于类。
    4、静态成员函数与普通成员函数的区别:
         静态成员函数不包含指向具体对象的指针;
         普通成员函数包含一个指向具体对象的指针
  • 相关阅读:
    2星|《所有的工作都可以用一张纸画完》
    1星|《我怎么没想到》:古龙武侠小说风格,有故事没细节,没有实际的商业价值
    3星|《三联生活周刊》2017年45期:盒马鲜生四不像
    3星|《如何激励你的员工》:优秀的企业管理者擅长问问题
    Android 用MediaCodec实现视频硬解码(转)
    ISO/IEC 14496 文档内容简介, MPEG标准
    The h.264 Sequence Parameter Set
    World’s Smallest h.264 Encoder
    linux socket中的SO_REUSEADDR
    Bootstrap
  • 原文地址:https://www.cnblogs.com/yuehouse/p/9810740.html
Copyright © 2011-2022 走看看