迭代器性能

2024-01-28

与直接使用指针相比,实现和使用迭代器是否会带来任何类型的性能损失?

(假设我们使用最高的编译器优化...)

代码来自http://www.cplusplus.com/reference/iterator/iterator/ http://www.cplusplus.com/reference/iterator/iterator/

// std::iterator example
#include <iostream>     // std::cout
#include <iterator>     // std::iterator, std::input_iterator_tag

class MyIterator : public std::iterator<std::input_iterator_tag, int>
{
  int* p;
public:
  MyIterator(int* x) :p(x) {}
  MyIterator(const MyIterator& mit) : p(mit.p) {}
  MyIterator& operator++() {++p;return *this;}
  MyIterator operator++(int) {MyIterator tmp(*this); operator++(); return tmp;}
  bool operator==(const MyIterator& rhs) {return p==rhs.p;}
  bool operator!=(const MyIterator& rhs) {return p!=rhs.p;}
  int& operator*() {return *p;}
};

int main () {
  int numbers[]={10,20,30,40,50};
  MyIterator from(numbers);
  MyIterator until(numbers+5);
  for (MyIterator it=from; it!=until; it++)
    std::cout << *it << ' ';
  std::cout << '\n';

  return 0;
}

用于迭代器的 gcc godbolt https://godbolt.org/g/X0sCcB

用于原始指针的 gcc godbolt https://godbolt.org/g/PQAJ51


实现和使用迭代器是否会引入任何类型的 与直接使用指针相比,性能损失?\

这个问题是有问题的,因为它假设all迭代器是内存中连续数组的迭代器。但迭代器是概括到一个指针。它也可能是链表、哈希图、红黑树等的迭代器。因此,在这种情况下,您无法真正将基于连续数组的迭代器与更复杂的迭代器的性能进行比较类型,如树木。

现在,让我换个方式问这个问题:

对连续数组实现和使用迭代器是否会引入任何类型的 与直接使用指针相比,性能损失?\

好吧,不是真的,编译器几乎剥离了大部分 C++ 类包装器,并将汇编代码优化为使用 C 指针生成的相同程序集。

不相信我?这是生成的汇编代码你的代码,使用 Visual Studio 2015 update 4,x64 编译:

int main() {
00007FF7A1D71000  mov         qword ptr [rsp+8],rbx  
00007FF7A1D71005  push        rdi  
00007FF7A1D71006  sub         rsp,40h  
00007FF7A1D7100A  mov         rax,qword ptr [__security_cookie (07FF7A1D75000h)]  
00007FF7A1D71011  xor         rax,rsp  
00007FF7A1D71014  mov         qword ptr [rsp+38h],rax  
00007FF7A1D71019  movdqa      xmm0,xmmword ptr [__xmm@000000280000001e000000140000000a (07FF7A1D732C0h)]  
00007FF7A1D71021  lea         rbx,[numbers]  
00007FF7A1D71026  movdqu      xmmword ptr [numbers],xmm0  
00007FF7A1D7102C  mov         dword ptr [rsp+30h],32h  
00007FF7A1D71034  mov         edi,5  
00007FF7A1D71039  nop         dword ptr [rax]  
00007FF7A1D71040  mov         edx,dword ptr [rbx]  
00007FF7A1D71042  mov         rcx,qword ptr [__imp_std::cout (07FF7A1D73080h)]  
00007FF7A1D71049  call        qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A1D73088h)]  
00007FF7A1D7104F  mov         rcx,rax  
00007FF7A1D71052  mov         dl,20h  
00007FF7A1D71054  call        std::operator<<<std::char_traits<char> > (07FF7A1D71110h)  
00007FF7A1D71059  lea         rbx,[rbx+4]  
00007FF7A1D7105D  sub         rdi,1  
00007FF7A1D71061  jne         main+40h (07FF7A1D71040h)  
00007FF7A1D71063  mov         rcx,qword ptr [__imp_std::cout (07FF7A1D73080h)]  
00007FF7A1D7106A  mov         dl,0Ah  
00007FF7A1D7106C  call        std::operator<<<std::char_traits<char> > (07FF7A1D71110h)  
00007FF7A1D71071  xor         eax,eax  
}

这是使用c指针的代码:

int main() {
    int numbers[] = { 10,20,30,40,50 };
    for (MyIterator it = numbers; it != numbers + 5; it++)
        std::cout << *it << ' ';
    std::cout << '\n';

    return 0;
}

int main() {
00007FF6A72E1000  mov         qword ptr [rsp+8],rbx  
00007FF6A72E1005  push        rdi  
00007FF6A72E1006  sub         rsp,40h  
00007FF6A72E100A  mov         rax,qword ptr [__security_cookie (07FF6A72E5000h)]  
00007FF6A72E1011  xor         rax,rsp  
00007FF6A72E1014  mov         qword ptr [rsp+38h],rax  
00007FF6A72E1019  movdqa      xmm0,xmmword ptr [__xmm@000000280000001e000000140000000a (07FF6A72E32C0h)]  
00007FF6A72E1021  lea         rbx,[numbers]  
00007FF6A72E1026  movdqu      xmmword ptr [numbers],xmm0  
00007FF6A72E102C  mov         dword ptr [rsp+30h],32h  
00007FF6A72E1034  mov         edi,5  
00007FF6A72E1039  nop         dword ptr [rax]  
00007FF6A72E1040  mov         edx,dword ptr [rbx]  
00007FF6A72E1042  mov         rcx,qword ptr [__imp_std::cout (07FF6A72E3080h)]  
00007FF6A72E1049  call        qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF6A72E3088h)]  
00007FF6A72E104F  mov         rcx,rax  
00007FF6A72E1052  mov         dl,20h  
00007FF6A72E1054  call        std::operator<<<std::char_traits<char> > (07FF6A72E1110h)  
00007FF6A72E1059  lea         rbx,[rbx+4]  
00007FF6A72E105D  sub         rdi,1  
00007FF6A72E1061  jne         main+40h (07FF6A72E1040h)  
00007FF6A72E1063  mov         rcx,qword ptr [__imp_std::cout (07FF6A72E3080h)]  
00007FF6A72E106A  mov         dl,0Ah  
00007FF6A72E106C  call        std::operator<<<std::char_traits<char> > (07FF6A72E1110h)  
00007FF6A72E1071  xor         eax,eax  
}

它们是相同的。

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

迭代器性能 的相关文章

  • EF Core Group By 翻译支持条件总和

    听说 EF Core 2 1 将支持翻译小组 我感到非常兴奋 我下载了预览版并开始测试它 但发现我在很多地方仍然没有得到翻译分组 在下面的代码片段中 对 TotalFlagCases 的查询将阻止翻译分组工作 无论如何 我可以重写这个以便我
  • C 编程 - 文件 - fwrite

    我有一个关于编程和文件的问题 while current NULL if current gt Id Doctor 0 current current gt next id doc current gt Id Doctor if curre
  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • GLKit的GLKMatrix“列专业”如何?

    前提A 当谈论线性存储器中的 列主 矩阵时 列被一个接一个地指定 使得存储器中的前 4 个条目对应于矩阵中的第一列 另一方面 行主 矩阵被理解为依次指定行 以便内存中的前 4 个条目指定矩阵的第一行 A GLKMatrix4看起来像这样 u
  • 为什么两个不同的 Base64 字符串的转换会返回相等的字节数组?

    我想知道为什么从 base64 字符串转换会为不同的字符串返回相同的字节数组 const string s1 dg const string s2 dq byte a1 Convert FromBase64String s1 byte a2
  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • 类模板参数推导 - clang 和 gcc 不同

    下面的代码使用 gcc 编译 但不使用 clang 编译 https godbolt org z ttqGuL template
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐