虚函数和性能 C++

2023-11-22

在您对重复的标题感到畏缩之前,另一个问题不适合我在这里问的问题(IMO)。所以。

我真的很想在我的应用程序中使用虚拟函数,让事情变得简单一百倍(这不是 OOP 的全部内容吗;))。但我在某处读到它们是以性能成本为代价的,除了过早优化的同样老套的炒作之外什么也没有,我决定在一个小型基准测试中快速尝试一下,使用:

CProfiler.cpp

#include "CProfiler.h"

CProfiler::CProfiler(void (*func)(void), unsigned int iterations) {
    gettimeofday(&a, 0);
    for (;iterations > 0; iterations --) {
        func();
    }
    gettimeofday(&b, 0);
    result = (b.tv_sec * (unsigned int)1e6 + b.tv_usec) - (a.tv_sec * (unsigned int)1e6 + a.tv_usec);
};

main.cpp

#include "CProfiler.h"

#include <iostream>

class CC {
  protected:
    int width, height, area;
  };

class VCC {
  protected:
    int width, height, area;
  public:
    virtual void set_area () {}
  };

class CS: public CC {
  public:
    void set_area () { area = width * height; }
  };

class VCS: public VCC {
  public:
    void set_area () {  area = width * height; }
  };

void profileNonVirtual() {
    CS *abc = new CS;
    abc->set_area();
    delete abc;
}

void profileVirtual() {
    VCS *abc = new VCS;
    abc->set_area();
    delete abc;
}

int main() {
    int iterations = 5000;
    CProfiler prf2(&profileNonVirtual, iterations);
    CProfiler prf(&profileVirtual, iterations);

    std::cout << prf.result;
    std::cout << "\n";
    std::cout << prf2.result;

    return 0;
}

起初我只做了 100 次和 10000 次迭代,结果令人担忧:非虚拟化为 4ms,虚拟化为 250ms!我几乎要“nooooooo”进去,但后来我将迭代次数提高到了 500,000 次左右;看到结果几乎完全相同(如果没有启用优化标志,速度可能会慢 5%)。

我的问题是,为什么与大量迭代相比,少量迭代会出现如此显着的变化?纯粹是因为虚拟函数在多次迭代时在缓存中很热吗?

免责声明
我知道我的“分析”代码并不完美,但它确实给出了对事物的估计,这才是这个级别上最重要的。另外,我问这些问题是为了学习,而不仅仅是为了优化我的应用程序。


我认为您的测试用例过于人为,没有任何重大价值。

首先,在分析函数内,您动态分配和释放对象以及调用函数,如果您只想分析函数调用,那么您应该这样做。

其次,您没有分析虚拟函数调用代表给定问题的可行替代方案的情况。虚函数调用提供动态调度。您应该尝试分析一种情况,例如使用虚拟函数调用作为使用开关型反模式的替代方案。

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

虚函数和性能 C++ 的相关文章

  • 编写/使用 C++ 库

    我正在寻找有关以下内容的基本示例 教程 如何用 C 编写 编译库 soLinux 的文件 dllWindows 文件 如何在其他代码中导入和使用这些库 The code r cc include t h int main f return
  • C 编程 - 文件 - fwrite

    我有一个关于编程和文件的问题 while current NULL if current gt Id Doctor 0 current current gt next id doc current gt Id Doctor if curre
  • WCF RIA 服务 - 加载多个实体

    我正在寻找一种模式来解决以下问题 我认为这很常见 我正在使用 WCF RIA 服务在初始加载时将多个实体返回给客户端 我希望两个实体异步加载 以免锁定 UI 并且我想利用 RIA 服务来执行此操作 我的解决方案如下 似乎有效 这种方法会遇到
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • 在 ASP.NET 5 中使用 DI 调用构造函数时解决依赖关系

    Web 上似乎充斥着如何在 ASP NET 5 中使用 DI 的示例 但没有一个示例显示如何调用构造函数并解决依赖关系 以下只是众多案例之一 http social technet microsoft com wiki contents a
  • C++ OpenSSL 导出私钥

    到目前为止 我成功地使用了 SSL 但遇到了令人困惑的障碍 我生成了 RSA 密钥对 之前使用 PEM write bio RSAPrivateKey 来导出它们 然而 手册页声称该格式已经过时 实际上它看起来与通常的 PEM 格式不同 相
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • 使用 x509 证书签署 json 文档或字符串

    如何使用 x509 证书签署 json 文档或字符串 public static void fund string filePath C Users VIKAS Desktop Data xml Read the file XmlDocum
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • 测试用例执行完成后,无论是否通过,如何将测试用例结果保存在变量中?

    我正在使用 NUNIT 在 Visual Studio 中使用 Selenium WebDriver 测试用例的代码是 我想在执行测试用例后立即在变量中记录测试用例通过或失败的情况 我怎样才能实现这一点 NUnit 假设您使用 NUnit
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable

随机推荐

  • Flutter Facebook 网页登录

    我已经尝试过Flutter Facebook 登录包 它在 android 中工作正常 但在 web 中我没有被重定向到 Facebook 进行身份验证 尝试过这个软件包的人可以帮忙吗 该插件不支持网页 但有人更新了代码以支持 romulo
  • 从列表集合中删除项目而不删除

    我正在制作一个集合 我需要从集合中删除一项并使用过滤 删除的集合 这是我的代码 public class Emp public int Id get set public string Name get set List
  • 在视频 FFmpeg 上添加图像叠加

    我有一个视频 test mp4 和一个图像 test png test png是一个黑色图像 中心有一个透明的 洞 我想使用 FFmpeg 显示test png在视频上方 所以我只能看到一圈视频 如果可能的话 调整大小test png适应视
  • USSD 消息中的最大字符数是多少?

    据我了解 USSD 消息由 160 个字节组成 对于 7 位数据编码方案 最大字符数为 160 8 7 即 182 个字符 我不清楚 UCS2 编码的最大字符数是多少 通常情况下 它会类似于 160 2 但我对此有一些复杂的信息 USSD
  • SSO - SAML,成功登录后将用户重定向到指定的登录页面

    我正在实施 SSO 其中我是身份提供商 现在我能够成功登录服务提供商 但它带我到主页 我想在发布响应时指定着陆页 URL 进行了很多搜索 但找不到任何令人信服的东西 不太清楚 SAML 响应的哪个元素带有登陆页面 URL 或者是我必须指定的
  • r - 投资组合优化 -solve.QP - 约束不一致

    我正在尝试使用solve QP来解决投资组合优化问题 二次问题 总计 3 项资产 有4个限制 权重之和等于 1 投资组合预期回报率为 5 2 每项资产权重大于0 每个资产权重小于 0 5 Dmat 是协方差矩阵 Dmat lt matrix
  • 使用 HTTPBuilder POST -> NullPointerException?

    我正在尝试发出一个简单的 HTTP POST 请求 但我不知道为什么以下失败 我尝试按照示例进行操作here 我不明白我哪里错了 例外 java lang NullPointerException at groovyx net http H
  • $(document).ready() 之后立即调用什么 jQuery 事件?

    我生成了很多 HTML document ready 我有一个简单的窗口系统 但它不仅是在 document ready 还有一些 HTML 元素 不同的 JS 文件将内容放入 document ready 我希望我的窗口系统在之后生成 d
  • SQL Max(日期) 不带分组依据

    我有下表 MemberID ServDate 001 12 12 2015 001 12 13 2015 001 12 15 2015 002 11 30 2015 002 12 04 2015 我想让它看起来像这样 MemberID Se
  • 为什么从 data.table 中选择列会产生副本?

    看来从 data table 中选择列 data table结果产生基础向量的副本 我说的是非常简单的列选择 按名称 没有要计算的表达式j并且没有要子集的行i 更奇怪的是 data frame 中的列子集似乎没有创建任何副本 我正在使用 d
  • .click()方法,浏览器支持

    我想使用js方法 click 如下 document getElementById id click 但由于它的工作至关重要 我想知道哪些浏览器支持 click 方法有 我遇到的唯一一个不支持的浏览器 click 是Safari Safar
  • 如何向现有通知负载添加属性?

    在 Rails 通知中 我订阅了 process action action controller 并且想向有效负载添加更多属性 我怎样才能做到这一点 我尝试过使用append info to payload 但这似乎没有任何作用 modu
  • $.each() jQuery 中的索引起始编号

    如何启动 jQuery each 索引从 1 而不是 0 开始 我正在使用 each 函数来填充选择框 所以在这里 我想从 1 开始填充选择框中的选项 因此 根据条件 我想在第一个索引 即 0 中添加选项 each So try each
  • 无法访问 JD-Eclipse 站点:http://java.decompiler.free.fr/?q=jdeclipse [关闭]

    Closed 这个问题是无关 目前不接受答案 我无法访问java反编译器站点 http java decompiler free fr q jdeclipse 它显示 403 错误 Erreur 403 拒绝 de Traitement d
  • 在视频中的移动物体上叠加图像(增强现实/OpenCv)

    我在用FFmpeg通过此命令在视频上叠加图像 表情符号 i inputfilePath filter complex 0 1 overlay enable between t startTime endTime v1 map v0 map
  • 如何在 SSIS 包中使服务器名称动态化

    我有许多 SSIS 包 它们都连接到同一个数据库 我不想将服务器名称硬编码到每个数据库中的数据库连接中 因为它与开发服务器和实时服务器不同 这些服务器名称可能会随着时间的推移而改变 我知道您可以将其放入配置文件中 但所有这些 SSIS 包都
  • 如何在Windows中用Java快速截取桌面(ffmpeg等)?

    我想使用 java 使用 FFMPEG 或其他解决方案来截取我的机器的屏幕截图 我知道linux可以在没有JNI的情况下使用ffmpeg 但是在Windows中运行它不起作用 并且可能需要 JNI 是否有一些简单的Java类 以及其他任何必
  • 如何使用 Visual Studio 将 Unicode 打印到 C 语言的输出控制台?

    正如问题所说 我必须做什么才能将 Unicode 字符打印到输出控制台 我必须使用什么设置 现在我有这个代码 wchar t text L the 来 wprintf L Text is s n text return EXIT SUCCE
  • 我可以使用 Google Maps API 显示自定义地图吗?

    我所说的自定义地图是指自定义地图图块 例如绘制另一个星球的地图 我环顾四周 但找不到任何资源来指导如何在 Google 或任何网站上执行此操作 我知道这是可能的 因为我以前在网站上看到过这样做 但不幸的是 具有该网站链接的网站已关闭 因此我
  • 虚函数和性能 C++

    在您对重复的标题感到畏缩之前 另一个问题不适合我在这里问的问题 IMO 所以 我真的很想在我的应用程序中使用虚拟函数 让事情变得简单一百倍 这不是 OOP 的全部内容吗 但我在某处读到它们是以性能成本为代价的 除了过早优化的同样老套的炒作之