【问题标题】:Why is the empty base class optimization (EBO) is not working in MSVC?为什么空基类优化 (EBO) 在 MSVC 中不起作用?
【发布时间】:2021-11-07 08:38:58
【问题描述】:

为什么空基类优化 (EBO) 没有在 Visual C++ 中得到充分应用?

如果我有很多基类,有什么方法可以帮助编译器进行这种优化?

#include <iostream>

struct T1 { };
struct T2 { };
struct T3 { };
struct T4 { };
struct T5 { };
struct T6 { };

struct Test : T1, T2, T3, T4, T5, T6 { };

int main() { std::cout << sizeof(Test); }   // Prints 5

【问题讨论】:

  • 你是在调试模式下编译吗?
  • 嗯...我没看到你有 6 个...这让事情变得更加混乱...
  • @Mysticial:是的,如果你把派生类也算进去的话,它是 7。这就是为什么它让我感到困惑哈哈。 (有趣的是,当你嵌套它们时它似乎也没有消失。我有一堆空类,每个类都有 1-2 个基类,但它们都相互继承,对象最终像 30字节!!)
  • g++ is working fine,这可能是 MS 特定的行为或必须设置调试标志。
  • 这种行为是 boost 运算符具有基类链接而不是简单地让用户进行多重继承的原因 boost.org/doc/libs/1_51_0/libs/utility/operators.htm#chaining

标签: c++ visual-c++ compiler-optimization empty-class


【解决方案1】:

这是 Visual C++ 编译器中长期存在的错误。当一个类派生自多个空基类时,只有初始的空基类会使用空基优化 (EBO) 进行优化。

此问题于 2006 年在 Microsoft Connect 上报告:Empty Base Optimization Not Working Properly. 目前,旧错误在 Microsoft Connect 上不可见。我被告知这是一个暂时的问题,虽然我不知道什么时候会解决。同时,以下是来自 Visual C++ 编译器团队的开发人员之一 Jonathan Caves 对该错误的回应:

嗨:不幸的是,尽管这是 Visual C++ 对象模型中的一个错误,但我们目前无法修复它,因为修复它可能会破坏许多现有程序,因为对象的大小会发生变化。希望在未来我们能够解决这个问题,但在产品的下一个版本中不能解决。

感谢您报告问题。

【讨论】:

  • 我总是觉得有趣的是,当您真正需要 MSDN 链接时,它们会中断,至少他们计划修复它...
  • 这在 VS2017 中仍然是一个问题。但是,可以根据此blog post 进行一些手动操作来规避它。从 VS2015 Update 2 开始,可以将__declspec(empty_bases) 添加到派生类声明中,以强制在多继承场景中应用 EBO。这必须手动完成以保持二进制兼容性。
【解决方案2】:

“官方”的立场是 MSVC 只会为单一继承执行 EBO,不幸的是,说明这一点的错误报告已被 MS 删除,所以剩下的只是一个较旧的 question on MSDN 指出它并引用现在已删除的错误报告。

【讨论】:

    【解决方案3】:

    Visual Studio 2017 Update 2 起,there is a fix 用于此...但默认情况下是否禁用它。 而且您必须分别为每个类显式启用它:

        struct __declspec(empty_bases) Test : T1, T2, T3, T4, T5, T6 { };
        //     ^^^^^^^^^^^^^^^^^^^^^^^
    
        static_assert(1 == sizeof(Test));
    

    遗憾的是,即使在 Visual Studio 2019 中,/std:c++latest/permissive- 仍然如此:无法全局设置。

    【讨论】:

      猜你喜欢
      • 2011-05-18
      • 1970-01-01
      • 2020-04-26
      • 1970-01-01
      • 1970-01-01
      • 2013-12-09
      相关资源
      最近更新 更多