c++对象模型探索2.1:类对象所占用的空间

 

 

选自:https://www.cnblogs.com/cxq0017/p/10643466.html

一个类的实例化对象所占空间的大小? 注意不要说类的大小,是类的对象的大小。 首先,类的大小是什么?确切的说,类只是一个类型的定义,它是没有大小可言的,用sizeof运算符对一个类型名操作,得到的是具有该类型实体的大小

#include 

using namespace std;

class A
{
};

int main()
{
    A obj;
    int nLen = sizeof(obj);
    cout << nLen << endl; //sizeof(一个空类)为什么等于1?

    return 0;
}

一个空类对象的大小是1,为什么不是0?

  初学者肯定会很烦恼?类A明明是空类,它的大小应该为0,为什么编译器输出的结果为1呢?这就是实例化的原因(空类同样被实例化),每个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存中得到了独一无二的地址,所以obj的大小是1.

#include 

using namespace std;

class A
{
public:
    void func1() { };
    void  func2() { };
    void  func3() { };
};

int main()
{
    A obj;
    int nLen = sizeof(obj);
    cout << nLen << endl; //sizeof(一个空类)为什么等于1?

    return 0;
}

此时给类A添加了三个成员函数,此时的类A对象的大小是多少呢?

我们看到此时类A对象obj的大小还是1,说明类的成员函数不占用类对象的内存空间

c++对象模型探索2.1:类对象所占用的空间_第1张图片

可以看到原来0bj的内存地址上存储了63这个十六进制,而十六进制63对应的ASCII码刚好是字符c,所以说是一个字节大小。同时也说明了成员变量占用类对象的内存空间

#include 

using namespace std;

class A
{
public:
    void func1() { };
    void  func2() { };
    void  func3() { };
    //char ab;
    int nab;
};

int main()
{
    A obj;
    int nLen = sizeof(obj);
    cout << nLen << endl; //

    //obj.ab = 'c';
    obj.nab = 12;
    return 0;
}

c++对象模型探索2.1:类对象所占用的空间_第2张图片

    类的成员函数 不占用 类对象的内存空间
    我们已经知道两点:
    (1)成员函数不占用类对象的内存空间
    (2)一个类对象至少占用1个字节的内存空间
    (3)成员变量是占用对象的内存空间


    结论:成员变量是包含在每个对象中的,是占用对象字节的。
    而成员函数虽然也写在类的定义中,但成员函数不占对象字节数的(不占内存空间);
    成员函数 每个类只诞生 一个(跟着类走),而不管你用这个类产生了多少个该类的对象;

 

#include 

using namespace std;

class A{};
class B{};
class C : public A 
{
    virtual void func() = 0;
};

class D : public B, public C 
{

};

int main()
{
    cout << sizeof(A) << endl;//1
    cout << sizeof(B) << endl;//1

    cout << sizeof(C) << endl;//4
    cout << sizeof(D) << endl;//8

    return 0;
}

 

#include 

using namespace std;

class A{};
class B1{};
class B 
{
    char c;
};
class C : public A 
{
    virtual void func() = 0;
};

class D : public B, public C {};

class E :public B1, public C {};
int main()
{
    cout << sizeof(A) << endl; //1
    cout << sizeof(B) << endl; //1

    cout << sizeof(C) << endl;//4
    cout << sizeof(D) << endl;//8
    cout << sizeof(E) << endl;//8

    return 0;
}

类A,B的大小为1上面我们已经讲过原因,而类C是由类A派生出来的,它里面有一个纯虚函数,由于有虚函数的原因,有一个指向虚函数的指针(vptr),在32位的系统分配给指针的大小为4个字节,所以最后得到类C的大小为4个字节(类里只要有一个虚函数,或者说至少有一个虚函数,这个类就会产生一个指向虚函数的指针,有两个虚函数就会产生两个指向虚函数的指针,类本身,指向虚函数的指针(一个或者一堆)要有地方存放,这些指针就存放在一个表格里,这个表格我们称为“虚函数表”,这个虚函数表是保存在可执行文件中的,在程序执行的时候载入到内存中来。不管有几个虚函数,在32位的系统sizeof()都是多了4个字节)

类D的大小更让初学者疑惑,类D是由类B,C派生而来的,它的大小应该为二者之和5,为什么是8呢?这是因为为了提高实例在内存中的存取效率,类的大小往往被调整到系统的整数倍,并采取就近的法则,离哪个最近的倍数,就是该类的大小,所以类D的大小为8个字节。

下面我们再看一个例子:

#include 

using namespace std;

class A
{
private:
    int data;
};

class B
{
private:
    int data;
    static int xs;
};
int B::xs = 10;
int main()
{
    cout << sizeof(A) << endl;//4
    cout << sizeof(B) << endl;//4

    return 0;
}

为什么类B比类A多了一个数据成员,大小却和类A的大小相同呢?因为类B的静态数据成员被编译器放在程序的一个global data members中,它是类的一个数据成员,但是它不影响类的大小,不管这个类实际产生了多少实例,还是派生了多少新的类,静态成员在类中只有一个实体存在,而类的非静态数据成员只有被实例化的时候,他们才存在,但是类的静态数据成员一旦被声明,无论类是否被实例化,它都已经存在,可以这么说,类的静态数据成员是一种特殊的全局变量。

下面我们看一个有构造函数,和析构函数的类的大小,它又是多大呢?

#include 

using namespace std;

class A
{
public:
    A(int a) { x = a;  }
    void func() 
    {
        cout << x << endl;
    }

    ~A() { }
private:
    int x;
    int g;
};

class B 
{
public:
private:
    int a;
    int b;
    static int xs;
};

int B::xs = 20;

int main()
{
    A a(10);
    //a.func();

    B b;
    cout << sizeof(a) << endl;
    cout << sizeof(b) << endl;
    return 0;
}

它们的结果均相同,可以看出类的大小与它当中的构造函数,析构函数,以及其他的成员函数无关,只与它当中的成员数据有关.

 

从以上几个例子我们可以总结出来类的大小

1.为类的非静态成员数据的类型大小之和.
2.由编译器额外加入的成员变量的大小,用来支持语言的某些特性(如:指向虚函数的指针). 
3.为了优化存取效率,进行的边缘调整(字节对齐). 
4 与类中的构造函数,析构函数以及其他的成员函数无关.

另外:一个类对象至少占用1个字节的内存空间。

 

#include 
using namespace std;

class A
{
public:
	void func()  {}; //成员函数
	void func1() {}; //成员函数
	void func2() {}; //成员函数

	//char ab; //成员变量,char类型占一个字节内存
	int ab; //int类型占4个字节
};

//类对象所占用的空间
int main()
{
    //std::cout << "Hello World!\n"; 
	A obja,objb;
	int ilen = sizeof(obja); //sizeof(A)   = 1 ,为什么sizeof(空类) = 1 而不等于0?
	cout << ilen << endl;

	//类的成员函数 不占用 类对象的内存空间
	//我们已经知道两点:
	//(1)成员函数不占用类对象的内存空间
	//(2)一个类对象至少占用1个字节的内存空间
	//obja.ab = 'c';
	//(3)成员变量是占用对象的内存空间
	obja.ab = 12;
	objb.ab = 24;

	//结论:成员变量是包含在每个对象中的,是占用对象字节的。
	  //而成员函数虽然也写在类的定义中,但成员函数不占对象字节数的(不占内存空间);

	//成员函数 每个类只诞生 一个(跟着类走),而不管你用这个类产生了多少个该类的对象;

	return 1; 
}

你可能感兴趣的:(c++转载)