【问题标题】:What is the advantage of constexpr virtual functions in C++20?C++20 中 constexpr 虚函数有什么好处?
【发布时间】:2022-01-22 22:31:00
【问题描述】:

我可以很容易地说,通过将函数声明为 constexpr,我们在编译时对其进行评估,这样可以节省运行时的时间,因为结果已经生成。

另一方面,虚函数需要在运行时解析。因此,我想我们无法摆脱解决过程。由于constexpr函数的机制,只有结果可以快速获取。

constexpr virtual 函数还有其他好处吗?

【问题讨论】:

  • 小心你的第一句话。 constexpr 允许函数在编译时执行,它不强制它。如果你想强制执行,你必须使用consteval
  • “虚拟函数需要在运行时解析。” 一个常见的假设,但事实并非如此。如果类型未知,它们将在运行时解析。如果类型已知,编译器可以解析它。考虑ConcreteType c; c.virtualfunc(); 运行时是否需要检查是哪个函数?
  • 这能回答你的问题吗? Can virtual functions be constexpr?
  • @DrewDormann 是的,在这种情况下,我们实际上并不需要虚拟性。我在考虑指针类型。还是谢谢

标签: c++ c++20 constexpr virtual-functions constexpr-function


【解决方案1】:

显而易见的好处是您现在甚至可以在编译时进行虚函数调用。

struct Base {
    constexpr virtual int get() { return 1; }
    virtual ~Base() = default;
};

struct Child : Base {
    constexpr int get() override { return 2; }
};

constexpr int foo(bool b) {
    Base* ptr = b ? new Base() : new Child();
    auto res = ptr->get(); // this call is not possible prior to C++20
    delete ptr;

    return res;
}

constexpr auto BaseVal = foo(true);
constexpr auto ChildVal = foo(false);

在 C++20 之前,您不能通过常量表达式中的基指针使用 get 函数。如果你做到constexpr,你可以。 Example.


现在想一想我们可以在编译时从虚函数调用中获得什么好处:也许是编译时。 C++ 基本上有两种机制来处理多态性:

  • 模板和
  • 虚拟函数。

两者都解决了基本相同的问题,但在程序生命周期的不同阶段。当然,在编译时进行尽可能多的计算是很好的,因此在运行时具有最佳性能。但是,这并不总是一种可行的方法,因为模板的工作方式会导致编译时间迅速增加。

猜测从这里开始。现在,如果我们扩大可以调用虚函数的阶段并允许在编译时调用它们呢?在某些情况下,这将允许我们用虚函数调用替换大量递归或嵌套的模板。假设 constexpr 解释器比编译器递归解析模板更快,您可以看到一些编译时间减少。

当然,这一优势被您从概念和模块中获得的性能提升所掩盖。


另一个好处在于 constexpr 的一般性质:在持续评估期间禁止使用 UB。这意味着您可以通过一些静态断言来检查您的虚拟函数是否是 UB 免费的。

【讨论】:

  • 我也会在问题中添加工作示例代码,而不仅仅是“这不是它的工作方式”代码
  • 比编译时间更重要的是模板元编程逻辑(虽然它可以计算任何东西)是非常不透明的,本质上是一种不同的语言(功能性和纯粹的具有自己的数据结构和语法等)来自“实际”C++。如果您听听 C++ 委员会等的谈话,“constexpr Everything”的主要原因总是“所以编译时 C++ 可以像普通 C++ 一样看起来和被理解”。回避“模板语言”极其低效的“执行模型”是一个好处。
  • @HTNW 你是对的。我也考虑了可读性方面,但是当我达到我的推测结束时,我已经忘记了这一点。我猜我的编译时解释器有一些内存泄漏。哦,好吧...
  • @HTNW 为什么“模板语言”的“执行模型”效率非常低?
  • @CaglayanDOKME 模板“程序”通过实例化大量模板来执行,因此编译器必须处理可能永远不会在运行时出现的大量类和函数定义。例如。我刚刚测试的一个简单的模板级插入排序可以生成超过 260 个类来对 10 个元素进行排序。
猜你喜欢
  • 2021-02-20
  • 2023-01-23
  • 1970-01-01
  • 2020-01-20
  • 1970-01-01
  • 2011-05-16
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多