C++类的大小介绍

1、C++结构体和类的关系

为什么讲C++类的大小要提到结构体呢,因为可能很多和我一样的学子,接触过C语言的结构体对齐,但不明白类的大小怎么计算,这其中都要用到内存对齐的概念,对于内存对齐的概念之前已经说过了,可以参考这篇博客:C++结构体字节对齐和共用体大小  明白结构体的内存大小计算后,就要明白类和结构体的关系:

在C++中,结构体和类的唯一区别就是:  结构体和类具有不同的默认访问控制属性。

  类中,对于未指定访问控制属性的成员,其访问控制属性为私有类型(private)。

  结构体中,对于未指定任何访问控制属性的成员,其访问控制属性为公有类型(public)。

所以结构体的大小和类的大小是一样的,在C++中,结构体也可以实现实现继承和多态(可能很惊讶,可以去看看这篇博文:C++结构体与类的区别详情,还要明确,静态成员变量和成员函数所占用的空间肯定不是结构体或类的空间。还有就是空的类的大小是1字节,以方便类进行实例化。

代码进行验证:

#include <iostream>
using namespace std;

struct Node {

};

class Test{

};

int main () {
    cout << "sizeof(struct Node) = " << sizeof(Node) << endl;
    cout << "sizeof(class Test) =" << sizeof(Test) << endl;
    system("pause");
    return 0;

}

代码运行结果为:

2、继承类的大小

继承允许我们依据另一个类来定义一个类,会把一个类的成员大小都继承下来,所以继承了的派生类大小一定要考虑基类的大小,首先考虑的最大对齐数,派生类的最大对齐数要考虑基类的最大对齐数。

下面以实际代码进行说明:

#include <iostream>
using namespace std;

class Base{
public:
    void func() {  //成员函数不占用类的空间大小

    }
private:
    static int m_val1; // 静态成员不占用类的空间
    int m_valInt;
    char m_valChar;
    double m_valDouble;
};

class Son:public Base{
public:
    static int func() { //静态成员函数也不占用内存空间
        return 0;
    }
private:
    int m_sonValint;
};

int main () {
    cout << "sizeof(Base) = " << sizeof(Base) << endl;
    cout << "sizeof(Son)  = " << sizeof(Son) << endl;
    system("pause");
    return 0;

}

代码运行结果为:

可以明确,静态成员变量和成员函数所占用的空间类的空间,所以Base类的最大对齐数为double类型的大小(8字节),按照顺序存储,

Base类的大小计算应该为:

sizeof(Base)= 4 + 1 + 3(浪费) + 8 = 16字节

Son类继承了Base类,它的最大对齐数也就是8字节,

所以Son类的大小计算应该为:

sizeof(Son)  = 4 + 1 + 3(浪费) + 8 + 8 = 24字节

注意类的也要考虑存储顺序,如果把Base类中的m_valChar放到m_valDouble后面,

Base类的大小计算就变成了:

sizeof(Base)= 4 + 4(浪费)+ 8 + 1 + 7(浪费)= 24字节

Son类的大小就算就变成了:

sizeof(Son)= 4 + 4(浪费)+ 8 + 1 + 3(浪费) +  4= 24字节

由此可以推算出多继承类的大小计算,菱形继承也是一样,都会继承基类的内存,尤其注意虚继承的情况,虚继承只是避免了菱形继承出现的二义性,但不是不继承,

如以下代码:

#include <iostream>
using namespace std;

class Base{
public:
    void func() {  //成员函数不占用类的空间大小

    }
public:
    double m_valDouble;
};

class Son1:virtual public Base{}; //虚继承
class Son2:virtual public Base{}; //虚继承
class GrandSon:public Son1,public Son2{};

int main () {

    cout << "sizeof(GrandSon)  = " << sizeof(GrandSon) << endl;
    GrandSon gs;
    // gs.m_valDouble = 10; //如果不是虚继承就会出现二义性

    system("pause");
    return 0;

}

代码运行结果为:

上述GrandSon的依旧为16字节,因为它从Son1继承来了一份,又从Son2继承来了一份,所以,虚继承只是避免了访问的二义性,也可见菱形继承会对内存空间造成浪费 。

3、多态类的大小

多态类唯一的区别就是计算类大小要考虑到虚寒表指针的大小,指针的大小和系统相关,32位机器为4字节,64位机器为8字节,指针的大小也要作为最大对齐数的考虑范围。

代码说明如下:

#include <iostream>
using namespace std;

class Base{
public:
    virtual void func() = 0; //纯虚函数,会生成虚函数表指针
public:
    char m_valChar;
};

class Son: public Base{
public:
    void func() {};
public:
    int m_SonvalInt;
};

int main () {

    cout << "sizeof(Base) = " << sizeof(Base) << endl;
    cout << "sizeof(Son)  = " << sizeof(Son) << endl; 

    system("pause");
    return 0;

}

代码运行结果为:

Base类的大小为8字节,是因为虚函数表指针占用了4字节,所以Base类的最大对齐数为4字节,虚函数表在构造函数的时候就会生成,所以,虚函数表指针肯定优先存储,

所以Base类大小的计算为:

sizeof(Base) = 4 + 1 + 3(浪费) = 8字节

则Son类的大小计算为:

sizeof(Son)= 4 + 1 + 3(浪费) + 4 = 12字节

到此这篇关于C++类的大小介绍的文章就介绍到这了,更多相关C++类的大小内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++关于类结构体大小和构造顺序,析构顺序的测试详解

    目录 总结 #include <iostream> using namespace std; /** 1. c++的类中成员若不加修饰符的话,默认是private 2. 调用构造函数时,先递归调用最顶级的父类构造函数,再依次到子类的构造函数. 3. 调用析构函数时相反,先调用最底层的子类析构函数,再依次到父类的构造函数. 4. 空类的sizeof(A)大小为1,多个空类继承后的子类大小也是1 */ class A{ public: A() { cout<<"A const

  • C和C++中的基本数据类型的大小及表示范围详解

    本文研究的主要问题时关于C和C++中的基本数据类型int.long.long long.float.double.char.string的大小及表示范围,具体介绍如下. 一.基本类型的大小及范围的总结(以下所讲都是默认在32位操作系统下): 字节:byte:位:bit. 1.短整型short:所占内存大小:2byte=16bit: 所能表示范围:-32768~32767:(即-2^15~2^15-1) 2.整型int:所占内存大小:4byte=32bit: 所能表示范围:-2147483648~

  • 深入分析C++中类的大小

    首先看一个例子: 复制代码 代码如下: #include <iostream> using namespace std; class A{}; class B {     int b;     char c; }; class C {     int c1;         static int c2; }; int C::c2 = 1; class D:public C,public B{     int d; };  int main() {     cout<<"s

  • c++动态内存空间示例(自定义空间类型大小和空间长度)

    动态内存空间的申请示范 利用C++的特性,能够自定义空间的类型大小和空间长度 下面这个程序是个数组动态配置的简单示例 复制代码 代码如下: #include <iostream>using namespace std; int main(){   int size = 0; cout << "请输入数组长度:";  //能够自定义的动态申请空间长度    cin >> size;    int *arr_Point = new int[size];

  • C++空类及没有成员变量的类的大小实例分析

    众所周知的C++中空类的大小为1,但是除了空类之外的其他一些没有成员变量的类的大小,还是有相当一部分开发人员对此有很多不明之处的. 这里我们以如下代码为例: #include using namespace std; class a {}; class b{}; class c :public a{ virtual void fun() = 0; }; class d :public b, public c{}; int main() { cout << "sizeof(a)&quo

  • C++类的大小介绍

    1.C++结构体和类的关系 为什么讲C++类的大小要提到结构体呢,因为可能很多和我一样的学子,接触过C语言的结构体对齐,但不明白类的大小怎么计算,这其中都要用到内存对齐的概念,对于内存对齐的概念之前已经说过了,可以参考这篇博客:C++结构体字节对齐和共用体大小  明白结构体的内存大小计算后,就要明白类和结构体的关系: 在C++中,结构体和类的唯一区别就是:  结构体和类具有不同的默认访问控制属性. 类中,对于未指定访问控制属性的成员,其访问控制属性为私有类型(private). 结构体中,对于未

  • 基于StringUtils工具类的常用方法介绍(必看篇)

    前言:工作中看到项目组里的大牛写代码大量的用到了StringUtils工具类来做字符串的操作,便学习整理了一下,方便查阅. isEmpty(String str) 是否为空,空格字符为false isNotEmpty(String str) 是否为非空,空格字符为true isBlank(String str) 是否为空,空格字符为true isNotBlank(String str) 是否为非空,空格字符为false trim(String str)去除字符串两端的控制符,空字符串.null

  • Python爬虫之Spider类用法简单介绍

    一.网络爬虫 网络爬虫又被称为网络蜘蛛(

  • Java中关于Collections集合工具类的详细介绍

    Collections 是一个操作 Set.List 和 Map 等集合的工具类. Collections 中提供了一系列静态的方法对集合元素进行排序.查询和修改等操作,还提供了对集合对象设置不可变.对集合对象实现同步控制等方法. 排序操作 reverse(List):反转 List 中元素的顺序 shuffle(List):对 List 集合元素进行随机排序 sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序 sort(List,Comparator):根据指定的 C

  • C++中的类的大小详解

    目录 一.普通类的大小 二.空类的大小 三.自动填充类或者结构体的大小 总结 一.普通类的大小 #include<iostream> using namespace std; class MyClass { public: MyClass(){ int i = 0; float f = 0.01f; }; int getI(){ return i; } int getF(){ return f; } private: int i; float f; //静态变量实际上是其全局变量,它存储在全局

  • Java String类和StringBuffer类的区别介绍

    关于java的字符串处理我们一般使用String类和StringBuffer类 那么String类和StringBuffer类的区别在什么地方呢? 1.String是不可变的.StringBuffer是可变的.在程序中如果定义String s = "this is a string".那么在以后的应用中不能对s进行任何修改只能进行诸如subString等操作,如果想进行改动只能重新new一个string而不是对原来的s进行改动.而对于StringBuffer却是可以改变的,在程序中定义

  • Java Calendar日历类的使用介绍

    目录 创建一个Candendar对象 Calendar的常用方法 创建一个Candendar对象 我们都知道创建一个类的对象最简单的方法是从他的构造方法入手,我们看一下它的构造方法. protected Calendar() { this(TimeZone.getDefaultRef(), Locale.getDefault(Category.FORMAT)); this.sharedZone = true; } protected Calendar(TimeZone var1, Locale

  • [ASP.NET AJAX]Function对象及Type类的方法介绍

    上一回我们从总体上认识了JavaScript Microsoft AJAX Library由于临时有事,没有加入事例显得有点抽象,这一回一定会通过一些事例更加直观的来会一会Asp.NET Ajax脚本库中一个很是重要的类Type.这个类提供了一些扩展面向对象编程的一些反射方法,通过这个类我们可以注册类似.NET中的一些(如:命名空间,类,枚举等等)基本类型.这个Type类继承自window是一个Global类型,不属于任何命名空间.下面我们来看看Type中的一些基本方法以及是怎样实一些方法的实现

  • Java工具类BeanUtils库介绍及实例详解

    BeanUtils工具由Apache软件基金组织编写,提供给我们使用,主要解决的问题是:把对象的属性数据封装到对象中. 在整个J2EE的编程过程中,我们经常会从各种配置文件中读取相应的数据,需要明白的一点是从配置文件中读取到的数据都是String,但是很显然我们的应用程序中不仅仅有String一种数据类型,比如:基本数据类型(int.double.char.float等),还有自定义数据类型(引用数据类型), 那么我们必须面临的一个问题就是讲字符串类型转换为各种具体的数据类型,该怎么办呢? 有两

随机推荐