类和对象(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、静态成员函数与普通成员函数的区别:
     静态成员函数不包含指向具体对象的指针;
     普通成员函数包含一个指向具体对象的指针

 

转载于:https://www.cnblogs.com/yuehouse/p/9810740.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值