2016-09-18 139 views
2

與直接使用指針相比,實現和使用迭代器是否會引入任何類型的性能損失?迭代器性能

(假設我們用最高的編譯器優化...)

的代碼是從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 for iterator

gcc godbolt for raw pointer

+0

只是一個評論;你可能想更喜歡[cppreference](http://cppreference.com/)在cplusplus.com作爲參考網站... –

+0

@JesperJuhl這樣的宗教,沒有根據和禿頂的建議使一個想要使用cplusplus.com作爲參考網站。 –

+0

@ÖöTiib無論如何。隨你做。但cplusplus.com往往有不準確,明顯錯誤和不完整的內容。 cppreference.com往往有更完整和更準確的內容。但使用任何你喜歡的.. –

回答

3

是否直接使用指針實現和使用迭代器引入任何形式的 性能損失,在比較呢?\

這個問題是有問題的,因爲它假定所有迭代器迭代器內存中的連續數組。但迭代器是一個泛化到一個指針。它也可能是鏈表,哈希映射,紅黑樹等的迭代器,所以在這種情況下,您無法真正將基於連續數組的迭代器的性能與更復雜的迭代器進行比較類型,像樹。

現在,讓我問的問題是不同的:

是否實施和使用迭代器的連續陣列引入任何形式的 性能損失,相比於直接使用指針\

好吧,不是真的,編譯器幾乎剝離了大部分C++類包裝器,並將彙編代碼優化爲使用C指針生成的相同程序集。

不相信我?這裏是從代碼生成的彙編代碼,用視覺工作室編譯2015更新4,64:

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 [[email protected] (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 [[email protected] (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 
} 

它們是相同的。

+0

謝謝。很高興知道。 – rxu

+0

_it假設所有的迭代器都是迭代器,以便在內存中連續存儲數組._ - 問題是如何假設的? –

+1

@MaximEgorushkin - 這是因爲問題是關於使用指針的性能。用簡單的指針,數據必須是連續的。 –

4

如果迭代函數可以再內聯抽象的運行時成本爲0.

這是斯特勞斯稱零開銷抽象Foundations of C++

一般情況下,C++實現服從 零開銷原則:你不要用什麼,你不支付。更進一步:你使用的是什麼,你無法更好地使用代碼。

零開銷抽象機制。 「輕量級抽象」指的是抽象方法不會將空間或時間開銷強加於對抽象的特定示例進行細緻的手工編碼所施加的過量空間或時間開銷。

基準得到硬數字。