📜  C++中的随机访问迭代器

📅  最后修改于: 2021-05-30 15:17:26             🧑  作者: Mango

在经过各种STL算法(例如std :: nth_element和std :: sort)的模板定义之后,您必须找到它们的模板定义,该模板定义由类型为Random-access Iterator的对象组成。那么,它们是什么?为什么要使用它们?

随机访问迭代器是C++标准库中存在的五种主要迭代器之一,其他类型是Input迭代器Output迭代器Forward迭代器Bidirectional迭代器

随机访问迭代器是一种迭代器,可用于相对于它们所指向的元素的任意偏移位置访问元素,并提供与指针相同的功能。就功能而言,随机访问迭代器是最完整的迭代器。所有指针类型也是有效的随机访问迭代器。

要注意的是,像vector,deque这样的容器都支持随机访问迭代器。这意味着,如果我们为它们声明普通迭代器,则这些迭代器将是随机访问迭代器,就像在list,map,multimap,set和multiset的情况下,它们是双向迭代器。

因此,从上述层次结构可以说,随机访问迭代器是所有迭代器类型中最强的。

显着特征

  1. 可用性:随机访问迭代器可用于多遍算法中,即涉及在不同遍中多次处理容器的算法。
  2. 相等/不相等比较:可以将随机访问迭代器与另一个迭代器进行相等性比较。由于迭代器指向某个位置,因此这两个迭代器仅在指向相同位置时才相等,否则就不相等。

    因此,如果A和B是随机访问迭代器,则以下两个表达式有效:

    A == B  // Checking for equality
    A != B  // Checking for inequality
    
  3. 取消引用:可以将随机访问迭代器同时作为rvalue和lvalue进行解引用。
    // C++ program to demonstrate Random-access iterator
    #include
    #include
    using namespace std;
    int main()
    {
        vectorv1 = {10, 20, 30, 40, 50};
      
        // Declaring an iterator
        vector::iterator i1;
      
        for (i1=v1.begin();i1!=v1.end();++i1)
        {
            // Assigning values to locations pointed by iterator
            *i1 = 7;
        }
      
        for (i1=v1.begin();i1!=v1.end();++i1)
        {
            // Accessing values at locations pointed by iterator
            cout << (*i1) << " ";
        }
          
        return 0;
    }
    

    输出:

    7 7 7 7 7
    

    因此,正如我们在此处看到的那样,我们既可以访问迭代器,也可以为其分配值,因此,迭代器是一个随机访问迭代器。

  4. 可递增的:可以对随机访问迭代器进行递增,以便使用运算符++()引用序列中的下一个元素,如前一代码所示,其中i1在for循环中递增。

    因此,如果A是随机访问迭代器,则以下两个表达式有效:

    A++   // Using post increment operator
    ++A   // Using pre increment operator
    
  5. 可减少的:就像我们可以将运算符++()与随机访问迭代器一起使用来增加它们一样,我们也可以减少它们。
    // C++ program to demonstrate Random-access iterator
    #include
    #include
    using namespace std;
    int main()
    {
        vectorv1 = {1, 2, 3, 4, 5};
      
        // Declaring an iterator
        vector::iterator i1;
      
        // Accessing the elements from end using decrement
        // operator
        for (i1=v1.end()-1;i1!=v1.begin()-1;--i1)
        {
             
            cout << (*i1) << " ";
              
        }
        return 0;
    }
    

    输出:

    5 4 3 2 1
    

    因为,我们从向量的结尾开始,然后通过递减指针而朝起点移动,这表明递减运算符可与此类迭代器一起使用。

  6. 关系运算符:虽然,双向迭代器无法与=等关系运算符一起使用,但是层次结构中较高的随机访问迭代器支持所有这些关系运算符。
    If A and B are Random-access iterators, then
    
    A == B     // Allowed
    A <= B     // Allowed
    
  7. 算术运算符: -等方面的关系运算符一样,他们也可以用算术运算运算符如+,使用。这意味着随机访问迭代器可以在两个方向上移动,也可以太随机地移动。
    If A and B are Random-access iterators, then
    
    A + 1     // Allowed
    B - 2     // Allowed
    
    // C++ program to demonstrate Random-access iterator
    #include
    #include
    using namespace std;
    int main()
    {
        vectorv1 = {1, 2, 3, 4, 5};
      
        // Declaring first iterator
        vector::iterator i1;
      
        // Declaring second iterator
        vector::iterator i2;
      
        // i1 points to the beginning of the list
        i1 = v1.begin();
      
        // i2 points to the end of the list
        i2 = v1.end();
      
        // Applying relational operator to them
        if ( i1 < i2)
        {
            cout << "Yes";
        } 
      
        // Applying arithmetic operator to them
        int count = i2 - i1;
      
        cout << "\ncount = " << count;
        return 0;
    }
    

    输出:

    Yes
    count = 5
    

    在这里,由于i1指向起点,而i2指向终点,因此i2会大于i1,并且它们之间的差就是它们之间的总距离。

  8. 使用偏移量解除引用运算符([]):随机访问迭代器支持偏移量解除引用运算符([]),该运算符用于随机访问。
    If A is a Random-access iterator, then
    A[3]    // Allowed 
    
    // C++ program to demonstrate Random-access iterator
    #include
    #include
    using namespace std;
    int main()
    {
        vectorv1 = {1, 2, 3, 4, 5};
        int i;
      
        // Accessing elements using offset dereference
        // operator [ ]
        for(i=0;i<5;++i)
        {
            cout << v1[i] << " ";
        }
        return 0;  
    }
    

    输出:

    1 2 3 4 5
    
  9. 可交换的:这些迭代器指向的值可以交换或交换。

实际实施

了解了它的功能之后,了解它的实际实现也非常重要。如前所述,随机访问迭代器可用于所有目的和每种情况。以下STL算法显示了其实际实现之一:

  • std :: random_shuffle:众所周知,该算法用于随机地重排容器中存在的所有元素。因此,让我们看一下它的内部工作原理(不要只关注可以在其中使用随机访问迭代器的地方):
    // Definition of std::random_shuffle()
    template 
    void random_shuffle(RandomAccessIterator first,
                        RandomAccessIterator last,
                        RandomNumberGenerator& gen)
    {
        iterator_traits::difference_type i, n;
        n = (last - first);
        for (i=n-1; i>0; --i) 
        {
            swap (first[i],first[gen(i+1)]);
        }
    }
    

    在这里,我们可以看到我们使用了随机访问迭代器,因为没有其他类型的迭代器支持算术运算运算符,这就是我们使用它的原因。

实际上,如果您正在考虑使用随机访问迭代器,则可以使用随机访问迭代器来代替任何其他类型的迭代器,因为它是C++标准库中最强大和最佳的迭代器类型。

要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”