程序员何时使用空基优化(EBO)

Naw*_*waz 19 c++ optimization memory-management class compiler-optimization

我正在阅读有关空基优化(EBO)的内容.在阅读时,我脑海中浮现出以下问题:

  1. 对类派生类没有任何贡献(无论是功能方面还是数据方面),使用Empty类作为基类有什么意义

  2. 本文中,我读到了这个:

// S是空
类struct T:S
{
      int x;
};

[...]

请注意,我们没有丢失任何数据或代码准确性:当您创建S类型的独立对象时,对象的大小仍然是之前的1(或更多); 只有当S被用作另一个类的基类时,它的内存占用量才会缩小到零.为了实现这种节省的影响,想象一个包含125,000个对象的向量.仅EBO就可以节省半兆内存!

这是否意味着如果我们不使用"S"作为"T"的基类,我们必然会消耗两倍的兆字节内存?我认为,这篇文章比较了我认为不正确的两种不同情景.

我想知道一个真实的情景时,EBO可以证明是有用的.(手段,在相同的情况下,我们就一定是在亏损,如果我们不使用EBO!).

请注意,如果您的答案包含以下解释:

整点是一个空类的大小非零,但是当派生或派生时它的大小为零,那么我就不会问这个,正如我所知道的那样.我的问题是,为什么有人会从一个空洞的班级中获得他的班级?即使他没有衍生出来并简单地写出他的课程(没有任何空基础),他是否会以任何方式迷失?

ice*_*ime 36

EBO在基于策略的设计环境中非常重要,您通常会从多个策略类中私下继承.如果我们以线程安全策略为例,可以想象伪代码:

class MTSafePolicy
{
public:
  void lock() { mutex_.lock(); }
  void unlock() { mutex_.unlock(); }

private:
  Mutex mutex_;
};

class MTUnsafePolicy
{
public:
  void lock() { /* no-op */ }
  void unlock() { /* no-op */ }
};
Run Code Online (Sandbox Code Playgroud)

给定基于策略的设计类,例如:

template<class ThreadSafetyPolicy>
class Test : ThreadSafetyPolicy
{
  /* ... */
};
Run Code Online (Sandbox Code Playgroud)

使用这个类MTUnsafePolicy简单地添加没有大小的类Test:它是一个完美的例子,不支付你不使用的东西.


Let*_*_Be 7

EBO实际上并不是一个优化(至少不是你在代码中做的那个).整点是空类具有非零大小,但是在派生或派生时它可以具有零大小.

这是最常见的结果:

class A { };
class B { };

class C { };
class D : C { };

#include <iostream>
using namespace std;

int main()
{
        cout << "sizeof(A) + sizeof(B) == " << sizeof(A)+sizeof(B) << endl;
        cout << "sizeof(D) == " << sizeof(D) << endl;

        return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

sizeof(A) + sizeof(B) == 2
sizeof(D) == 1
Run Code Online (Sandbox Code Playgroud)

编辑:优化是,如果你实际上派生(例如从仿函数,或从只有静态成员的类),你的类(即派生)的大小不会增加1(或由于填充字节,更可能是4或8).


Sum*_*uma 6

EBO中的"优化"意味着使用基类的情况可以优化使用比使用相同类型的成员更少的内存.你比较一下

struct T : S 
{
      int x;
};
Run Code Online (Sandbox Code Playgroud)

struct T
{
      S s;
      int x;
};
Run Code Online (Sandbox Code Playgroud)

没有

struct T
{
      int x;
};
Run Code Online (Sandbox Code Playgroud)

如果你的问题是为什么你会有一个空类(作为成员或作为基础),那是因为你使用它的成员函数.空意味着它没有数据成员,而不是它根本没有任何成员.这样的事情通常在使用模板进行编程时完成,其中基类有时是"空的"(没有数据成员),有时不是.


小智 5

当程序员想要在不增加客户端类大小的情况下向客户端公开一些数据时使用它。空类可以包含枚举和类型定义或一些客户端可以使用的定义。使用这样的类的最明智的方法是,私下继承这样的类。这将从外部隐藏数据,并且不会增加您的班级规模。