C++ でイテレータを逆参照する

Zeeshan Afridi 2023年10月12日
  1. C++ の反復子とは
  2. C++ での逆参照
  3. C++ で反復子を逆参照できない理由
C++ でイテレータを逆参照する

イテレータは、C++ のもう 1つの強力なメカニズムであり、配列など、内部に要素のインデックスがないツリーやセットのような複雑なデータ構造を反復処理するのに役立ちます。

C++ の反復子とは

C++ では、反復子はポインターのようなオブジェクトであり、配列、リスト、およびその他のデータ構造内の要素を指します。 コンテナー要素を反復するために反復子を使用します。 従来のループを使用することもできますが、イテレーターはコンテナーの反復処理において優位に立っています。

コンテナの要素をトラバースするための非常に一般的なアプローチを提供します。

配列のような一般的なデータ構造では、インデックス変数を使用してコンテナーをループできますが、ループするインデックス変数がないツリーや順序付けられていないデータ構造などの高度なデータ構造では、イテレーターを使用してそれをトラバースします。 .

コンテナはイテレータにデータ型を提供し、コンテナ クラスはイテレータがコンテナの要素を繰り返し処理するのに役立つ 2つの基本的な関数を提供します。

  1. Begin() - コンテナの最初の要素を返します。
  2. End() - コンテナの最後の要素の次の要素を返します。

適切なコード例を通して理解しましょう。

#include <iostream>
#include <vector>
using namespace std;

int main() {
  // Declaring a vector
  vector<int> numbers = {1, 2, 3, 4, 5};

  // Declaring an iterator
  vector<int>::iterator i;

  int j;
  cout << "Traversing using loop = ";

  // Accessing the elements using loops
  for (j = 0; j < 5; ++j) {
    cout << numbers[j] << ", ";
  }

  cout << endl << "Traversing using Iterators = ";

  // Accessing the elements using iterators
  for (i = numbers.begin(); i != numbers.end(); ++i) {
    cout << *i << ", ";
  }

  // Adding another element to the vector
  numbers.push_back(6);

  cout << endl << "Traversing using loops after adding new value to numbers = ";

  // After adding a new value to the numbers vector
  for (j = 0; j < 5; ++j) {
    cout << numbers[j] << ", ";
  }

  cout << endl
       << "Traversing using iterators after adding new value to numbers = ";

  // Accessing the elements using iterators
  for (i = numbers.begin(); i != numbers.end(); ++i) {
    cout << *i << ", ";
  }
  return 0;
}

出力:

Traversing using loop = 1, 2, 3, 4, 5,
Traversing using Iterators = 1, 2, 3, 4, 5,
Traversing using loops after adding new value to numbers = 1, 2, 3, 4, 5,
Traversing using iterators after adding new value to numbers = 1, 2, 3, 4, 5, 6,

このプログラムは、ループと反復子を使用してコンテナーを通過する使用方法の違いを示しています。 上記のコードでは、反復子はコードを追跡し、コードに変更が加えられた場合に動的に適用します。

ループ中は、ループ用のコードを静的に更新する必要があります。 イテレータは、コードの再利用率を達成しています。

イテレータでは、begin() 関数がコンテナの最初の要素を取得し、end() が最後の要素の次の要素を取得します。

C++ での逆参照

C++ の逆参照演算子は、ポインターが指すメモリ位置のデータにアクセスまたは操作するために使用されます。 * アスタリスク記号 は、ポインター変数を差分するときにポインター変数と共に使用され、ポインターの逆参照と呼ばれる、ポイントされた変数を参照します。

コード例:

#include <iostream>
using namespace std;

int main() {
  int a = 9, b;
  int *p;  // Un-initialized Pointer
  p = &a;  // Store the address of a in pointer p
  b = *p;  // Put the Value  of the pointer p in b
  cout << "The value of a        =   " << a << endl;
  cout << "The value of pointer p =   " << *p << endl;
  cout << "The value of b        =   " << b << endl;
}

出力:

The value of a        =   9
The value of pointer p =   9
The value of b        =   9

最初に a に 9 を代入し、次にポインター p を定義します。 次にポインタであるpaのアドレスを代入し、最後に整数データ型の変数bにポインタを代入します。

表示すると、ap、および b は 9 と同じ出力を得ています。これは、pa のアドレスを持っているためです。これは、どこでも使用して a の値を表示するのに役立ちます。

C++ で反復子を逆参照できない理由

C++ では、end() 関数がイテレーターとオブジェクトをポインターとして返すため、イテレーターをすぐに逆参照することはできません。これはデータ構造の有効なメンバーではありません。

最後に逆参照すると、エラーがスローされます。これは、エンド ポインターの目的は、いつ到達したかを確認することだけであるためです。

Begin()は、コンテナが空でない場合、つまりこの条件を満たす場所を返します。

v.begin() != v.end()  // this condition checks, if the container is empty or not

ただし、最後の要素にアクセスする必要がある場合は、以下のコードを使用できます。

vector<object>::const_iterator i = vectorOfObjects.end();
i--;
cout << *i << endl;  // this prints the last element of the container

注意として、このコードは、ベクターに少なくとも 1つの要素が含まれている場合にのみ機能します。

コード例:

#include <iostream>
#include <string>
#include <vector>

using namespace std;
struct Student {
  int roll;
  string name;
  int age;
};

int main() {
  Student s1, s2, s3;  // Objects of strucu
  vector<Student> ListOfStudents;

  s1.roll = 1;  // populating the data members of Student
  s2.roll = 2;
  s3.roll = 3;

  s1.name = "Mike";
  s2.name = "John";
  s3.name = "Tom";

  s1.age = 15;
  s2.age = 16;
  s3.age = 14;

  ListOfStudents.push_back(s1);
  ListOfStudents.push_back(s2);
  ListOfStudents.push_back(s3);

  vector<Student>::const_iterator iter =
      ListOfStudents.begin();  // begining position

  while (iter != ListOfStudents.end()) {  // if the container is empty or not
    cout << "Roll number " << iter->roll << " is " << (*iter).name
         << " and he is " << iter->age << " years old." << endl;
    ++iter;
  }
  return 0;
}

出力:

Roll number 1 is Mike and he is 15 years old.
Roll number 2 is John and he is 16 years old.
Roll number 3 is Tom and he is 14 years old.
著者: Zeeshan Afridi
Zeeshan Afridi avatar Zeeshan Afridi avatar

Zeeshan is a detail oriented software engineer that helps companies and individuals make their lives and easier with software solutions.

LinkedIn

関連記事 - C++ Iterator