C++中自定义类型的大小由若干因素共同决定,这些因素包括数据成员的大小(成员函数不会影响类型大小)、内存对齐机制、继承关系、模板类的实例化等。
我们通过几个示例来具体看一下这些因素是怎么影响自定义类型大小的。
情况一:自定义类型大小受数据成员的影响,但不受成员函数的影响。
代码示例:
#include<iostream>
class DemoA
{
private:
int m_iData;
};
class DemoB
{
public:
int Func() { return 0; }
private:
int m_iData;
};
int main()
{
std::cout << "sizeof(DemoA):" << sizeof(DemoA)
<< ", sizeof(DemoB):" << sizeof(DemoB)
<< std::endl;
return 0;
}
这个示例的打印结果是sizeof(DemoA):4, sizeof(DemoB):4
。
分析:上面这个示例中DemoA和DemoB的区别就在于DemoB多了一个成员函数Func,但是DemoA和DemoB的大小一致,因为自定义类型的大小不受成员函数的影响。
那数据成员又是怎么影响自定义类型大小的呢,答案是自定义类型的大小是所有数据成员所占内存大小之和(注意这里是所占内存而不是实际使用内存,二者是有区别的,参考情况二),这个示例中DemoA和DemoB都是只有一个int类型的数据成员,这个数据成员占了4个字节的内存,所以DemoA和DemoB的大小都是4个字节。
情况二:自定义类型大小受内存对齐机制的影响。
代码示例:
#include<iostream>
class DemoA
{
private:
char m_cDataA;
char m_cDataB;
int m_iData;
};
class DemoB
{
private:
char m_cDataA;
int m_iData;
char m_cDataB;
};
int main()
{
std::cout << "sizeof(DemoA):" << sizeof(DemoA)
<< ", sizeof(DemoB):" << sizeof(DemoB)
<< std::endl;
return 0;
}
这个示例的打印结果是sizeof(DemoA):8, sizeof(DemoB):12
。
分析:这个示例中DemoA和DemoB都是只有一个int类型的数据成员和两个char类型的数据成员,但是DemoA和DemoB的大小却不同,这是因为数据成员的排列顺序不一样,受到内存对齐机制影响之后,占用的内存不一样。具体的内存占用机制这里不展开解释了,我们之前也简单介绍过C++内存对齐机制。
情况三:自定义类型大小受继承关系的影响。
代码示例:
#include<iostream>
class Demo
{
private:
int m_iData;
};
class DemoA :public Demo
{
private:
int m_iData;
};
class DemoB
{
private:
int m_iData;
};
int main()
{
std::cout << "sizeof(DemoA):" << sizeof(DemoA)
<< ", sizeof(DemoB):" << sizeof(DemoB)
<< std::endl;
return 0;
}
这个示例的打印结果是sizeof(DemoA):8, sizeof(DemoB):4
。这个继承关系只是表象因素,根本因素还是数据成员以及内存对齐机制,DemoA继承自Demo,所以DemoA的数据成员也包括从Demo继承来的数据成员。
情况四:自定义类型大小受模板类的实例化的影响。
代码示例:
#include<iostream>
template<typename T>
class Demo
{
private:
T m_data;
};
int main()
{
std::cout << "sizeof(Demo<char>):" << sizeof(Demo<char>)
<< ", sizeof(Demo<int>):" << sizeof(Demo<int>)
<< std::endl;
return 0;
}
打印结果是sizeof(Demo<char>):1, sizeof(Demo<int>):4
,这个模板实例化也是表象因素,根本因素还是数据成员以及内存对齐机制。
看几个特殊的示例。
代码示例:
#include<iostream>
class Demo {};
int main()
{
std::cout << "sizeof(Demo):" << sizeof(Demo) << std::endl;
return 0;
}
这个示例的打印结果是sizeof(Demo):1
,这是一条规则,空类型(不包含任何数据成员的类型,成员函数不影响)大小为1,算是留了个占位符。
代码示例:
#include<iostream>
class Demo
{
public:
virtual int Func() { return 0; }
};
int main()
{
std::cout << "sizeof(Demo):" << sizeof(Demo) << std::endl;
return 0;
}
这个示例的打印结果是sizeof(Demo):8
,或许有人会问了,这个类型不是不包含数据成员吗,大小不应该是1吗,其实包含了一个叫做虚指针的指针类型的数据成员,这个跟虚函数的机制有关,这里不展开解释了,我们之前也简单介绍过C++中多态的底层实现机制。
如果这篇文章对你有帮助,别忘了关注我啊,可能我还会写出更多对你有帮助的文章
因篇幅问题不能全部显示,请点此查看更多更全内容