03-1 成员变量和成员函数分开存储
在类中,无论是变量还是函数我们都称之为:成员。
在 c++中,类内的成员变量和成员函数是分开存储的。
只有非静态成员变量才属于类的对象上。
我们先创建一个空的类,看看占用的内存大小是多少。
#include <iostream>
using namespace std;
class test
{
};
void main()
{
class test t1;
cout << "t1的大小 " << sizeof(t1) << endl;
}
运行结果:
t1的大小 1
空对象占用的内存大小为:1。这是因为c++的编译器会给每个空对象也分配一个字节的空间,为了区分空对象占内存的位置。每一个空对象也应该有一个独一无二的内存空间。
我们再来看看非空类所占用的内存空间大小:
#include <iostream>
using namespace std;
class test
{
int m_A;
};
void main()
{
class test t2;
cout << "t2的大小 " << sizeof(t2) << endl;
}
运行结果:
t2的大小 4
可以看到,分配给这个非空的类的对象了 4 个字节的大小,而单个int
所占用的内存大小正好是 4 个字节。
如果一个类没有成员变量,那么会分配 1 个字节的内存空间。而如果一个类存在成员变量,则这个类的单个成员占用的内存大小是这个类中所有成员变量的数据类型的总和(但是会遵循内存对齐)。
比如,如果类中有一个int
,那么就占用 4 个字节。如果有两个int
和一个double
,那么就占用 16 个字节。
请注意,这里面存在内存对齐的说法。具体来说,如上面的例子,如果一个类中有如果有一个int
和一个double
,所占用的内存空间大小也是 16 个字节。
-
内存对齐:
我们用一个例子试一下:
#include
using namespace std; class test { int m_A; double m_B; }; void main() { class test t2; cout << "t2的大小 " << sizeof(t2) << endl; cout << "double的大小 " << sizeof(double) << endl; cout << "int的大小 " << sizeof(int) << endl; } 在这里面,我们创建了一个类,叫做
test
。这个类内存在两个成员变量,一个是int
数据类型,另外一个是double
数据类型。int
数据类型占用 4 个字节大小的内存空间;double
数据类型占用 8 个字节大小的内存空间。运行结果:
t2的大小 16 double的大小 8 int的大小 4
运行之后我们会发现。存在一个
int
和一个double
的对象t2
,占用的大小是 16 个字节。而造成这样的原因就是:内存对齐。- 为什么需要内存对齐:
- 平台原因:不是所有的硬件都支持从任意的内存空间获取数据。如果不进行内存对齐,可能会出现硬件错误。
- 性能原因:好的没学到。
具体可以参考:一文轻松理解内存对齐 - 知乎 (zhihu.com)。
- 为什么需要内存对齐:
之前我们了解了类内对象的占用空间大小。如果我们此时将类内对象修改为静态成员变量的话:
#include <iostream>
using namespace std;
class test
{
static int m_A;
};
void main()
{
class test t2;
cout << "t2的大小 " << sizeof(t2) << endl;
}
在这里,在类test
中,只存在一个静态成员变量。这时候我们创建一个对象打印一下 ta 的大小。
t2的大小 1
会发现t2
的所占用的内存空间大小是1 个字节。这是因为静态成员变量不属于类对象上。
当然,像这样的也不会影响类的对象的大小:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
#include <iostream>
using namespace std;
class test
{
void test1()
{
}
static void test2()
{
}
};
void main()
{
class test t2;
cout << "t2的大小 " << sizeof(t2) << endl;
}
t2的大小 1
- 总结:
- 只有非静态成员变量属于类对象上。其他的(比如说静态成员变量、成员函数)都不属于类的对象上。
- 类内为空的时候,这个类的对象占用的内存空间是 1 个字节。
:-)