2016-09-18 9 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

ただのコメントです。参照サイトとしてcplusplus.comよりも[cppreference](http://cppreference.com/)の方が好きかもしれません。 –

+0

@JesperJuhlこのような宗教的で非地面的な大胆な提案は、cplusplus.comを参照サイト。 –

+0

@ÖöTiib何でも。好きにしてください。しかし、cplusplus.comは間違った、明らかに間違った、不完全な内容の傾向があります。 cppreference.comはより完全でより正確な内容を持つ傾向があります。しかし、あなたが好きなものを使用してください.. –

答えて

3

は直接ポインタを使用して比較して、実装するとイテレータは パフォーマンスの低下のいずれかの種類を紹介し使用していますか?\

それはすべてイテレータはにイテレータあると仮定し、この質問は、問題がありますメモリ内の連続した配列。イテレータは一般化のポインタです。ハッシュマップ、赤黒のツリーなどのイテレータでも構いません。この場合、連続した配列ベースのイテレータのパフォーマンスと、より複雑なイテレータのパフォーマンスを実際に比較することはできません木のような種類。今

、私は違った質問をしてみましょう:

直接ポインタ\

使用と比較して、 パフォーマンスペナルティのいずれかの種類を紹介実装し、連続した配列にイテレータを使用していますか?を

コンパイラはほとんどのC++クラスラッパーをほとんど取り除き、C-ポインタを使用して生成された同じアセンブリにアセンブリコードを最適化します。

私を信じられませんか?ここでのVisual Studio 2015のアップデート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 [[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です。

これはStroustrup氏はゼロ・オーバーヘッド抽象化Foundations of C++呼ぶものである。一般的には

、C++の実装は ゼロ・オーバーヘッドの原則に従う:あなたが使用していない何を、あなたが払っていません。そしてさらに:あなたが使っていることは、コードを手渡すことができませんでした。

ゼロオーバーヘッド抽象化メカニズム。 「軽量抽象化」とは、抽象化の特定の例を慎重に手作業でコーディングすることによって課されるものを超える余分なスペースまたは時間オーバーヘッドを課さない抽象化を意味する。

ベンチマークでは難しい数字が表示されます。

関連する問題