迭代器性能

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(使用前将#替换为@)

迭代器性能 的相关文章

  • 静态只读字符串数组

    我在我的 Web 应用程序中使用静态只读字符串数组 基本上数组有错误代码 我将所有类似的错误代码保存在一个数组中并检查该数组 而不是检查不同常量字符串中的每个错误代码 like public static readonly string m
  • 计算 XML 中特定 XML 节点的数量

    请参阅此 XML
  • 适合初学者的良好调试器教程[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有谁知道一个好的初学者教程 在 C 中使用调试器 我感觉自己好像错过了很多 我知道怎么做 单步执行代码并查看局部变量 虽然这常常给我带来问
  • 如何在多线程C++ 17程序中交换两个指针?

    我有两个指针 pA 和 pB 它们指向两个大的哈希映射对象 当pB指向的哈希图完全更新后 我想交换pB和pA 在C 17中 如何快速且线程安全地交换它们 原子 我是 c 17 的新手 2个指针的原子无等待交换可以通过以下方式实现 inclu
  • 如何捕获未发送到 stdout 的命令行文本?

    我在项目中使用 LAME 命令行 mp3 编码器 我希望能够看到某人正在使用什么版本 如果我只执行 LAME exe 而不带参数 我会得到 例如 C LAME gt LAME exe LAME 32 bits version 3 98 2
  • GetType() 在 Type 实例上返回什么?

    我在一些调试过程中遇到了这段代码 private bool HasBaseType Type type out Type baseType Type originalType type GetType baseType GetBaseTyp
  • 如何在C(Linux)中的while循环中准确地睡眠?

    在 C 代码 Linux 操作系统 中 我需要在 while 循环内准确地休眠 比如说 10000 微秒 1000 次 我尝试过usleep nanosleep select pselect和其他一些方法 但没有成功 一旦大约 50 次 它
  • 查找进程的完整路径

    我已经编写了 C 控制台应用程序 当我启动应用程序时 不使用cmd 我可以看到它列在任务管理器的进程列表中 现在我需要编写另一个应用程序 在其中我需要查找以前的应用程序是否正在运行 我知道应用程序名称和路径 所以我已将管理对象搜索器查询写入
  • C# 数据表更新多行

    我如何使用数据表进行多次更新 我找到了这个更新 1 行 http support microsoft com kb 307587 my code public void ExportCSV string SQLSyntax string L
  • 从客户端访问 DomainService 中的自定义对象

    我正在使用域服务从 Silverlight 客户端的数据库中获取数据 在DomainService1 cs中 我添加了以下内容 EnableClientAccess public class Product public int produ
  • 将 Long 转换为 DateTime 从 C# 日期到 Java 日期

    我一直尝试用Java读取二进制文件 而二进制文件是用C 编写的 其中一些数据包含日期时间数据 当 DateTime 数据写入文件 以二进制形式 时 它使用DateTime ToBinary on C 为了读取 DateTime 数据 它将首
  • 识别 Visual Studio 中的重载运算符 (c++)

    有没有办法使用 Visual Studio 快速直观地识别 C 中的重载运算符 在我看来 C 中的一大问题是不知道您正在使用的运算符是否已重载 Visual Studio 或某些第三方工具中是否有某些功能可以自动突出显示重载运算符或对重载运
  • 在 NaN 情况下 to_string() 可以返回什么

    我使用 VS 2012 遇到了非常令人恼火的行为 有时我的浮点数是 NaN auto dbgHelp std to string myFloat dbgHelp最终包含5008角色 你不能发明这个东西 其中大部分为0 最终结果是 0 INF
  • 保护 APK 中的字符串

    我正在使用 Xamarin 的 Mono for Android 开发一个 Android 应用程序 我目前正在努力使用 Google Play API 添加应用内购买功能 为此 我需要从我的应用程序内向 Google 发送公共许可证密钥
  • WPF DataGridTemplateColumn 组合框更新所有行

    我有这个 XAML 它从 ItemSource 是枚举的组合框中选择一个值 我使用的教程是 http www c sharpcorner com uploadfile dpatra combobox in datagrid in wpf h
  • 在屏幕上获取字符

    我浏览了 NCurses 函数列表 似乎找不到返回已打印在屏幕上的字符的函数 每个字符单元格中存储的字符是否有可访问的值 如果没有的话Windows终端有类似的功能吗 我想用它来替换屏幕上某个值的所有字符 例如 所有a s 具有不同的特征
  • 堆栈是向上增长还是向下增长?

    我在 C 中有这段代码 int q 10 int s 5 int a 3 printf Address of a d n int a printf Address of a 1 d n int a 1 printf Address of a
  • 如何在richtextbox中使用多颜色[重复]

    这个问题在这里已经有答案了 我使用 C windows 窗体 并且有 richtextbox 我想将一些文本设置为红色 一些设置为绿色 一些设置为黑色 怎么办呢 附图片 System Windows Forms RichTextBox有一个
  • Objective-C / C 给出枚举默认值

    我在某处读到过关于给枚举默认值的内容 如下所示 typedef enum MarketNavigationTypeNone 0 MarketNavigationTypeHeirachy 1 MarketNavigationTypeMarke
  • 灵气序列解析问题

    我在使用 Spirit Qi 2 4 编写解析器时遇到一些问题 我有一系列键值对以以下格式解析

随机推荐