虚函数和性能 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++ 的相关文章

  • Linq - 从表达式 创建表达式

    我有一个谓词Expression
  • 是否有可能劫持标准输出

    我正在尝试使用 C 重定向 Windows XP 上已运行进程的标准输出 我知道如果我自己生成进程 我可以做到这一点 但对于这个应用程序 我更喜欢一个 监听器 我可以附加到另一个进程 这在纯 Net 中可能吗 如果不可能 在 Win32 中
  • 局部函数声明有什么用处吗?

    大多数像我这样的 C 程序员都曾犯过以下错误 class C int main C c declares a function c taking no arguments returning a C not as intended by m
  • 在没有 epsilon 的情况下可以将浮点数与 0.0 进行比较吗?

    我知道 要比较两个浮点值 需要使用一些 epsilon 精度 因为它们并不精确 但是 我想知道是否存在边缘情况 我不需要那个 epsilon 特别是 我想知道这样做是否总是安全的 double foo double x if x lt 0
  • 当我在 MySQL 中使用 UUID 作为主键时,会如何影响性能

    我想知道当我在 MySQL 中使用 UUID 作为主键时 会对服务器的性能产生怎样或多大的影响 我想你正在使用InnoDB 无论如何你应该 因此 请阅读 高性能 MySQL 2ed 第 117 页中的以下章节 一般来说 从性能的角度来看 U
  • 嵌入资源文件的路径

    我的资源文件中有一个图标 我想引用它 这是需要图标文件路径的代码 IWshRuntimeLibrary IWshShortcut MyShortcut MyShortcut IWshRuntimeLibrary IWshShortcut W
  • 无法加载程序集问题

    我收到以下错误 无法加载程序集 错误详细信息 System BadImageFormatException 无法加载文件或程序集 文件 或其依赖项之一 该程序集是由比当前加载的运行时更新的运行时构建的 无法加载 该程序集是使用 Net Fr
  • C# 枚举到字符串自动转换?

    是否可以让编译器自动将我的 Enum 值转换为字符串 这样我就可以避免每次都显式调用 ToString 方法 这是我想做的一个例子 enum Rank A B C Rank myRank Rank A string myString Ran
  • 我在使用 ado.net 时收到错误 Argument 2 may not be pass with ref keywords

    int t 0 cmd Parameters AddWithValue Res ref t 我在第二行收到错误 参数 2 不能与 ref 关键字一起传递 您只能通过引用传递参数ref if the 范围 is a ref参数也是如此 Add
  • 在 C# 中使用命名空间别名有什么好处? [复制]

    这个问题在这里已经有答案了 使用命名空间别名有什么好处 仅仅是为了简化编码吗 仅当与类发生冲突时我才使用名称空间别名 对我来说 这根本没有简化 我的意见是 如果没有必要 就不要使用
  • DataGridView 行背景颜色没有改变

    我想根据加载时的特定条件更改 DGV 行的背景颜色 即使在 Windows 窗体中也是如此 但我看不到任何 DGV 行的颜色有任何变化 谁能告诉我如何解决这个问题 private void frmSecondaryPumps Load ob
  • 传递数组时在 C 中的函数参数中强制指定数组大小

    Context 在 C 中 我有一个以数组作为参数的函数 该参数用作该函数的输出 输出的大小始终相同 我会 让阅读代码的人清楚所需的大小 不过它已经在函数注释中了 理想情况下 编译会输出警告或错误 这样我就可以在编译时而不是运行时防止出现问
  • valgrind 在 Raspberry Pi 上返回未处理的指令

    我最近一直在尝试在运行 Debian GNU Linux7 0 喘息 的树莓派 型号 b 上使用 valgrind 来调试分段错误 每次我在编译的 C 程序上运行 valgrind 时 都会得到类似以下内容的信息 disInstr arm
  • 如何同步nosql db(ravendb)中的更改

    我已经开始在 RavenDB 的示例上学习 NoSQL 我从一个最简单的模型开始 假设我们有由用户创建的主题 public class Topic public string Id get protected set public stri
  • 如何从 Access 数据库中读取“是/否”值作为布尔值?

    帮我找回YES NO来自 MS Access 的布尔格式数据类型 我尝试解析它 但它总是返回 false 更新 实际上不是问题抱歉 它确实接受 YES NO 作为布尔值 OleDbconnection dbConnect new OleDb
  • Xcode 7 调试器不会中断内联标头函数

    过去五年我一直在各种 C 项目中使用 Xcode 没有出现这个问题 今天 我打开了一个较旧的项目 大约 2 年前 并尝试通过在该函数中放置一个活动断点来调试头文件中的内联函数 由于某种原因 调试器不会中断此代码 但是 如果我在调用该函数的
  • 为什么在构造函数中设置字段是(或不是)线程安全的?

    假设您有一个像这样的简单类 class MyClass private readonly int a private int b public MyClass int a int b this a a this b b public int
  • 在windows + opengl中选择图形设备

    我知道如何使用 openGL 打开窗口 使用 Win32 或其他工具包 但是当系统有2块显卡时 如何选择要渲染的图形设备 我的编程语言是 C 我专注于 Windows 但任何示例都将受到欢迎 编辑 也许更好地解释我的问题是个好主意 以便添加
  • 将一个 IEnumerable 拆分为多个 IEnumerable

    我是 linq 新手 我需要根据指示器将 Couple string text bool Indicator 类型的 IEnumerable 拆分为多个 IEnumerable 我尝试使用skipWhile 和 TakeWhile 但没有找
  • 如何使用 C# 为 azure devops 变量赋值

    我有 selenium C 测试脚本 可以从浏览器获取令牌 我有两个 azure devops 任务 一个用于执行 selenium 测试 另一个用于执行 API 测试 我想将 selenium 测试获取的令牌传递给 API 测试执行任务

随机推荐

  • 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 的全部内容吗 但我在某处读到它们是以性能成本为代价的 除了过早优化的同样老套的炒作之