首页 > 编程语言 >C++ 空基类优化

C++ 空基类优化

时间:2024-03-21 16:11:24浏览次数:27  
标签:BaseEmpty 子类 基类 空类 C++ DerivedDeeperEmpty 优化 public

1. 继承体系中的内存模型

我们都知道,在C++中,不存在大小是零的类。即便是空类,也要占据一个字节,否则无法比较两个空类对象是否是同一个对象(在C/C++中,默认使用地址来判断两个变量是否是同一个)。

class BaseEmpty { 
public:
  	BaseEmpty() { std::cout<<"Base address:    "<< this << std::endl;}
};

int main(int argc, char const *argv[]) {

  	BaseEmpty empty_1{};
  	BaseEmpty empty_2{};
 
  	assert(&empty_1 != &empty_2); // 两个空类对象的地址肯定不同

  	std::cout<<sizeof(BaseEmpty{})<<std::endl; // 输出 1
}

子类继承父类,可以等效地看作子类将父类的成员变量复制到自己内存模型中。比如在下面的demo中,Dervied_1继承了父类BaseDerived_1的内存模型等效于Derived_2

class Base { 
public:
  	Base() = default;
private:
  	int num_{0};
  	bool state_{false};
};

class Derived_1 : public Base { 
public:
  	Derived_1() = default;
private:
  	std::string name_{"CPP"};
};

class Derived_2 { 
public:
  	Derived_2() = default;
private:
  	int num_{0};
  	bool state_{false};
  	// 子类的成员变量
  	std::string name_{"CPP"};
};

2. 空基类优化

对于空类BaseEmpty ,假设有另一个空类DerivedEmpty继承自BaseEmpty,空类DerivedDeeperEmpty继承自DerivedEmpty,那么DerivedDeeperEmpty对象的大小sizeof(DerivedDeeperEmpty{})会是几个字节???

class DerivedEmpty: public BaseEmpty { 
public:
  DerivedEmpty() { 
    std::cout<<"Derived address: "<< this << std::endl;
  }
};

class DerivedDeeperEmpty: public DerivedEmpty {
public:
  DerivedDeeperEmpty() { 
    std::cout<<"deeper address:  "<< this << std::endl;
  }
};

如果仍然像之前说的那种内存等效模型,那么编译器会每个空基类对象都分配内存,因此即便DerivedDeeperEmpty是个空类,也要占用两个字节,相当于内部分别包含了BaseEmptyDerivedEmpty对象,即等效为类DerivedDeeperEmpty_eq

class DerivedDeeperEmpty_eq {
public:
  	DerivedDeeperEmpty_eq() = default;
private:
  	BaseEmpty    base_1_;
  	DerivedEmpty base_2_;
};

sizeof(DerivedDeeperEmpty_eq); // 2

如果编译器真的是这么实现,是否很不符合直觉。因为DerivedDeeperEmpty明明只是个空类啊!!!大小却是2个字节???如果情况再极端点,DerivedDeeperEmpty还有更深的空子类,那么空子类的大小会不断膨胀???

是的,这种情况太不符合直觉,严重浪费内存。因此,C++标准如下规定:在空类被用作基类时,如果不给它分配内存并不会导致它被存储到与同类型对象(包括子类对象)相同的地址上,那么就可以不给它分配内存。换句话说,BaseEmpty作为空基类时,下面两种情况,编译器不会为Basement对象在子类中分配内存:

  • 子类单继承,比如类DerivedDeeperEmpty。

  • 子类在多继承、选择第二个基类时,没有继续选择BaseEmptyBaseEmpty的子类作为父类,那么BaseEmpty是不会被分配内存的。

标签:BaseEmpty,子类,基类,空类,C++,DerivedDeeperEmpty,优化,public
From: https://www.cnblogs.com/love-9/p/18087611

相关文章

  • mysql语句优化心得
    一、常用SQL优化处理1.1like查询优化方案like模糊查询形如'%AAA%'和'%AAA'将不会使用索引,但是业务上不可避免可能又需要使用到这种形式查询方式:优化方案一:使用覆盖索引,即查询出的列只是用索引就可以获取,而无须查询表记录,这样也走了索引;优化方案二:使用locate函数或者positio......
  • 借助Numpy,优化Pandas的条件检索代码
    Numpy其实是最早的处理数据的Python库,它的核心ndarray对象,是一个高效的n维数组结构。通过这个库,可以高效的完成向量和矩阵运算,由于其出色的性能,很多其他的数据分析,科学计算或者机器学习相关的Python库都或多或少的依赖于它。Pandas就是其中之一,Pandas充分利用了NumPy的数组运算......
  • c/c++|gdb 单点调试 | 多点调试|查看栈中信息|具体变量
    设置断点,有什么好处,废话就不说了,可以去看手册设置断点,参考bxxx.cpp:n某个源文件的某行bfunc1调试某个函数编译g++test_gdb_watch.cpp-g设置断点bpowerr出现报错Missingseparatedebuginfos,use:debuginfo-installglibc-2.17-326.el7_9.x86_64libg......
  • C++ 对象模型
    1.普通类对象是什么布局?structBase{Base()=default;~Base()=default;voidFunc(){}inta;intb;};intmain(){Basea;return0;}2.带虚函数的类对象是什么布局?structBase{Base()=default;virtual~Base()......
  • 灰狼优化算法(MOGWO)
    灰狼优化算法(MOGWO)摘要固定大小的外部档案用来保存帕累托优化解在多目标搜索空间中,这个档案被用来定义狼群社会等级和捕猎行为这个算法在10个多目标测试集进行测试,并与MOEA/D和MOPSO进行对比引言将多个目标集成一个单一的目标两个缺点:一个均匀分布的权重不能保证生成......
  • c++模板
    前言大家好,我是jiantaoyab,这篇文章给大家带来c++模板的介绍,模板是泛型程序设计的基础,模板就是类或者函数的蓝图,后一篇文章我将开始介绍STL,模板在STL中大量的运用。模板分为函数模板和类模板函数模板格式template<typenameT1,typenameT2,......,typenameTn>//参数......
  • unity学习(66)——控制器Joystick Pack优化
    JoystickPack这种重力带惯性不利于正常开发。决定进行优化。有一种万事俱备只欠东风的感觉。源代码如下: 1.在脚本中找到轮盘所输出的方向值2.把方向的改变值加到鸣人模型身上。2.1控制器脚本中添加model变量2.2在unity中赋值 2.3代码中修改位置usingSystem.Col......
  • C++ 合成默认构造函数
    问题:C++面向对象编程时,如果我们没有声明任何构造函数constructor,按照以前最初学习,说编译器会自动合成一个默认的无参构造函数defaultconstructor,但是事实确实是这样吗,存不存在例外呢,即使有合成构造函数,那么它又将对类数据进行怎样的初始化呢?1.问题一如果我们没有声明任何构造......
  • C++ RTTI
    1.背景RTTI的英文全称是"RuntimeTypeIdentification",中文称为"运行时类型识别",它指的是程序在运行的时候才确定需要用到的对象是什么类型的。用于在运行时(而不是编译时)获取有关对象的信息。在C++中,由于存在多态行为,基类指针或者引用指向一个派生类,而其指向的真正类型,在编译阶......
  • C++标准库容器选择
    C++标准库提供了多种容器,每种容器都有其自身的特点和适用场景。以下是C++标准库中常用的容器以及它们的特点:std::vector:动态数组,支持随机访问,适用于需要快速随机访问元素的场景。std::list:双向链表,支持快速插入和删除操作,适用于需要频繁插入和删除元素的场景。std::deque......