可以在 C++ 中缓存虚函数查找吗?

2024-01-26

假设我在抽象基类指针 mypointer->foo() 上有一个虚拟函数调用 foo()。当我的应用程序启动时,根据文件的内容,它选择实例化特定的具体类并将 mypointer 分配给该实例。在应用程序的剩余生命周期中,mypointer 将always指向该具体类型的对象。我无法知道这个具体类型是什么(它可能由动态加载库中的工厂实例化)。我只知道在第一次创建具体类型的实例后,该类型将保持不变。指针可能并不总是指向同一个对象,但该对象将始终具有相同的具体类型。请注意,从技术上讲,类型是在“运行时”确定的,因为它基于文件的内容,但在“启动”(加载文件)之后,类型是固定的。

然而,在 C++ 中,每次在应用程序的整个持续时间内调用 foo 时,我都会支付虚拟函数查找成本。编译器无法优化查找,因为它无法知道具体类型在运行时不会改变(即使它是有史以来最令人惊奇的编译器,它也无法推测动态加载的行为图书馆)。在 Java 或 .NET 等 JIT 编译语言中,JIT 可以检测到同一类型被反复使用并执行内联缓存 http://en.wikipedia.org/wiki/Inline_caching。我基本上正在寻找一种方法来手动为 C++ 中的特定指针执行此操作。

C++ 有没有办法缓存这个查找?我意识到解决方案可能相当黑客。如果可以编写配置测试来发现 ABI/编译器的相关方面,使其“实际上可移植”,即使不是真正可移植的,我愿意接受 ABI/编译器特定的 hack。

更新:致反对者:如果这不值得优化,那么我怀疑现代 JIT 是否会这样做。您是否认为 Sun 和 MS 的工程师在实现内联缓存方面浪费了时间,并且没有对其进行基准测试以确保有所改进?


虚拟函数调用有两个成本:vtable 查找和函数调用。

vtable 查找已经由硬件处理。现代 CPU(假设您使用的不是非常简单的嵌入式 CPU)将在其分支预测器中预测虚拟函数的地址,并推测性地与数组查找并行执行它。事实上,vtable 查找与函数的推测执行并行发生,这意味着,在您描述的情况下在循环中执行时,与直接的非内联函数调用相比,虚拟函数调用的开销几乎为零。

我过去实际上已经测试过这个,尽管是使用 D 编程语言,而不是 C++。当在编译器设置中禁用内联并且我在循环中调用同一函数数百万次时,无论该函数是否为虚拟函数,时间都在彼此的 epsilon 范围内。

虚拟函数的第二个也是更重要的成本是它们在大多数情况下阻止函数的内联。这比听起来更重要,因为内联是一种优化,可以实现其他几种优化,例如在某些情况下进行常量折叠。没有办法在不重新编译代码的情况下内联函数。 JIT 可以解决这个问题,因为它们在应用程序执行期间不断重新编译代码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

可以在 C++ 中缓存虚函数查找吗? 的相关文章

  • 使用 std::packaged_task/std::exception_ptr 时,线程清理程序报告数据争用

    我遇到了线程清理程序 TSan 的一些问题 抱怨某些生产代码中的数据争用 其中 std packaged task 通过将它们包装在 std function 中而移交给调度程序线程 对于这个问题 我简化了它在生产中的作用 同时触发 TSa
  • 在 C++ 中使用 matlab 结构(matlab 函数调用的返回值)(由 matlab 编译器生成的库)

    你好 我有一个相当简单的 matlab 函数 例如 function MYSTRUCT myfunc MYSTRUCT prop1 test MYSTRUCT prop2 foo MYSTRUCT prop3 42 end 我用 matla
  • 如何让 Swagger 插件在自托管服务堆栈中工作

    我已经用 github 上提供的示例重新提出了这个问题 并为任何想要自己运行代码的人提供了一个下拉框下载链接 Swagger 无法在自托管 ServiceStack 服务上工作 https stackoverflow com questio
  • 提交后禁用按钮

    当用户提交付款表单并且发布表单的代码导致 Firefox 中出现重复发布时 我试图禁用按钮 去掉代码就不会出现这个问题 在firefox以外的任何浏览器中也不会出现这个问题 知道如何防止双重帖子吗 System Text StringBui
  • C中的malloc内存分配方案

    我在 C 中尝试使用 malloc 发现 malloc 在分配了一些内存后浪费了一些空间 下面是我用来测试 malloc 的一段代码 include
  • 使用 Newtonsoft 和 C# 反序列化嵌套 JSON

    我正在尝试解析来自 Rest API 的 Json 响应 我可以获得很好的响应并创建了一些类模型 我正在使用 Newtonsoft 的 Json Net 我的响应中不断收到空值 并且不确定我的模型设置是否正确或缺少某些内容 例如 我想要获取
  • 如何区分用户点击链接和页面自动重定向?

    拥有 C WebBrowser control http msdn microsoft com en us library system windows forms webbrowser aspx在我的 WinForms 应用程序中 并意识
  • 获取两个工作日之间的天数差异

    这听起来很简单 但我不明白其中的意义 那么获取两次之间的天数的最简单方法是什么DayOfWeeks当第一个是起点时 如果下一个工作日较早 则应考虑在下周 The DayOfWeek 枚举 http 20 20 5B1 5D 3a 20htt
  • 如何使用 LINQ2SQL 连接两个不同上下文的表?

    我的应用程序中有 2 个数据上下文 不同的数据库 并且需要能够通过上下文 B 中的表的右连接来查询上下文 A 中的表 我该如何在 LINQ2SQL 中执行此操作 Why 我们正在使用 SaaS 产品来跟踪我们的时间 项目等 并希望向该产品发
  • 由 IHttpClientFactory 注入时模拟 HttpClient 处理程序

    我创建了一个自定义库 它会自动为依赖于特定服务的 Polly 策略设置HttpClient 这是使用以下方法完成的IServiceCollection扩展方法和类型化客户端方法 一个简化的例子 public static IHttpClie
  • 是否有实用的理由使用“if (0 == p)”而不是“if (!p)”?

    我倾向于使用逻辑非运算符来编写 if 语句 if p some code 我周围的一些人倾向于使用显式比较 因此代码如下所示 if FOO p some code 其中 FOO 是其中之一false FALSE 0 0 0 NULL etc
  • DbContext 和 ObjectContext 有什么区别

    From MSDN 表示工作单元和存储库模式的组合 使您能够查询数据库并将更改分组在一起 然后将这些更改作为一个单元写回存储 DbContext在概念上类似于ObjectContext 我虽然DbContext只处理与数据库的连接以及针对数
  • C#:帮助理解 UML 类图中的 <>

    我目前正在做一个项目 我们必须从 UML 图编写代码 我了解 UML 类图的剖析 但我无法理解什么 lt
  • C# 中的合并运算符?

    我想我记得看到过类似的东西 三元运算符 http msdn microsoft com en us library ty67wk28 28VS 80 29 aspx在 C 中 它只有两部分 如果变量值不为空 则返回变量值 如果为空 则返回默
  • 使用管道时,如果子进程数量大于处理器数量,进程是否会被阻塞?

    当子进程数量很大时 我的程序停止运行 我不知道问题是什么 但我猜子进程在运行时以某种方式被阻止 下面是该程序的主要工作流程 void function int process num int i initial variables for
  • 方法优化 - C#

    我开发了一种方法 允许我通过参数传入表 字符串 列数组 字符串 和值数组 对象 然后使用这些参数创建参数化查询 虽然它工作得很好 但代码的长度以及多个 for 循环散发出一种代码味道 特别是我觉得我用来在列和值之间插入逗号的方法可以用不同的
  • C++ 条件编译

    我有以下代码片段 ifdef DO LOG define log p record p else define log p endif void record char data 现在如果我打电话log hello world 在我的代码中
  • 无法接收 UDP Windows RT

    我正在为 Windows 8 RT 编写一个 Windows Store Metro Modern RT 应用程序 需要在端口 49030 上接收 UDP 数据包 但我似乎无法接收任何数据包 我已按照使用教程进行操作DatagramSock
  • 当从finally中抛出异常时,Catch块不会被评估

    出现这个问题的原因是之前在 NET 4 0 中运行的代码在 NET 4 5 中因未处理的异常而失败 部分原因是 try finallys 如果您想了解详细信息 请阅读更多内容微软连接 https connect microsoft com
  • 从列表中选择项目以求和

    我有一个包含数值的项目列表 我需要使用这些项目求和 我需要你的帮助来构建这样的算法 下面是一个用 C 编写的示例 描述了我的问题 int sum 21 List

随机推荐

  • 如果用户在卸载后立即再次安装应用程序,GCM 是否会删除旧的注册 ID?

    我了解到 当 GCM 无法发送下一个推送通知时 GCM 会将注册 ID 标记为删除 但就我而言 我的用户发生了以下情况 Scenario 1 我的用户安装了该应用程序 并且他的设备已向 GCM 注册 2 同一用户立即卸载并再次安装该应用程序
  • Django:在模板中显示当前区域设置

    我需要将当前区域设置嵌入到 Django 模板的输出中 准确地说 作为 URL 的一部分 我知道我可以访问当前的language as LANGUAGE CODE if I load i18n 但有没有类似的方法来访问当前的locale 我
  • 如何测试角度装饰器功能

    我在 Angular 中有一个装饰器 它将扩展 log 服务的功能 我想测试它 但我没有找到实现此目的的方法 这是我的装饰器的存根 angular module myApp config function provide provide d
  • 如何在 PHP 中删除字符串的一部分? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何删除字符串的一部分 示例字符串 REGISTER 11223344 here 我怎样才能删除 11223344 从上面的示例字符串 如
  • 使用 Retrofit 和 Realm 纠正 RxJava 中的流程

    我正在结合 RxJava 和 Retrofit 来实现网络 API 并使用 Realm 作为数据库 我几乎可以正常工作 但我想知道这是否是正确的方法和事件流程 所以 这里是RetrofitApiManager public class Re
  • (xs : Vect n elem) -> Vect (n * 2) elem

    这本书使用 Idris 进行类型驱动开发 https www manning com books type driven development with idris提出这个练习 定义一个适合签名的可能方法 two xs Vect n el
  • 如何在没有嵌入式 tomcat 的情况下启动 Spring Boot 应用程序?

    我有一个使用 jhipster 生成的 Spring Boot 应用程序 它工作正常 但是 我还需要为一些后台批处理作业创建第二个应用程序 并且该应用程序使用第一个应用程序的大部分 Spring 服务 我所做的是创建第二个主类 它启动一个
  • 在 Visual Studio 中使用 Catch2 进行单元测试的最佳实践

    我是 C 单元测试的新手 想获得一些关于这方面的建议 我使用 Visual Studio 2019 进行开发 选择 Catch2 作为我的测试库 我还安装了 Catch2 的测试适配器 我在 GitHub 上阅读了 Catch2 和 Cat
  • 在 Cordova ios 4.0.0+ 中使用 Stripe Checkout

    我一直在尝试让 Stripe checkout 与 Cordova iOs 4 2 0 一起使用 但没有成功 适用的最后一个 Cordova iOs 版本是 3 9 2 为了测试 我制作了一个空的 hello world cordova 应
  • Google API:“invalid_grant”,但代码没有改变

    我在 Google API 身份验证方面遇到以下问题 PHP 致命错误 未捕获异常 Google Auth Exception 消息 刷新 OAuth2 令牌时出错 消息 错误 无效授权 在 home bot bot vendor goog
  • 混合 PCM 音频样本

    我有一个关于混合多个 PCM 样本的简单问题 我读到混合多个音频 PCM 样本的最佳方法是取每帧样本的平均值 因此 如果我在除以 5 之前将 5 个 16 位样本相加 显然很有可能它的值会大于 16 位 Short 所能容纳的值 因此 当将
  • 路由在 kubernetes 中无法使用 calico 工作

    I have kubernetes v1 6 0 由 kubeadm v1 6 1 设置 官方设置的 calicoyaml http docs projectcalico org v2 1 getting started kubernete
  • 如何在没有“未经检查”警告的情况下转换为(已知)泛型类型?

    我有这两个接口 public interface Event default void dispatch EventBus getInstance dispatch this public interface EventListener
  • NERDTree 自动加载特定目录

    我在 Windows 中使用 gvim 默认情况下 nerdtree 默认加载 C 驱动器 我想将其更改为 E 驱动器 如何实现这一点 每当我尝试使用 NERDTree 命令启动 NERDTree 时 都会收到此错误E492 Not an
  • 在内存中存储张量流模型

    我正在编写的程序涉及在运行时在模型之间进行切换 我当前正在使用 Saver 从磁盘保存 加载模型 如下所示 https www tensorflow org api docs python state ops saving and rest
  • VS Xamarin无法生成IPA文件

    我曾经将配置设置为 Release iPhone Remote Device 但是远程设备不再显示 只剩下本地设备 有谁知道有相关的设置吗 多谢 更新到 Visual Studio 16 11 3 远程设备 选项已恢复 看发行说明 http
  • 谷歌地图 API 风格的地图与卫星水

    我正在使用谷歌地图 API V3 创建一个样式化的地图 其中我使用自定义颜色 我想知道是否可以在使用陆地上的自定义样式的同时使用水域的卫星图像 IE 我希望水是卫星图像 而土地是自定义的纯色 现在我可以为土地和水提供自定义颜色 但我想知道是
  • 如何限制子类修改抽象类中方法的范围?

    如何限制抽象类的实现类将方法的范围从 protected 修改为 public 例如 假设我有一个抽象类 package com rao test public abstract class AbstractTEClass protecte
  • RISC-V 中的旋转位

    嘿 我对 RISC V 还算陌生 我的练习题之一是 将 0x0000000000000123 的值右移 4 位 预期结果为 0x3000000000000012 即所有十六进制数字向右移动一位 而最右边的一位移动到前面 到目前为止 我了解了
  • 可以在 C++ 中缓存虚函数查找吗?

    假设我在抽象基类指针 mypointer gt foo 上有一个虚拟函数调用 foo 当我的应用程序启动时 根据文件的内容 它选择实例化特定的具体类并将 mypointer 分配给该实例 在应用程序的剩余生命周期中 mypointer 将a