对于随机访问迭代器(矢量迭代器),迭代器是C ++样式指针吗?

时间:2020-01-05 06:16:12

标签: c++ iterator random-access

我有以下代码来随机化列表容器中的元素:

    #include <vector>
    #include <list>
    #include <iterator>
    #include <algorithm>
    #include <iostream>
    using namespace std;

        template<class RandomAccesIterator>
        void randomize(RandomAccesIterator iterBegin, RandomAccesIterator iterEnd)
        {
            while (iterBegin != iterEnd)
            {
                iter_swap(iterBegin, iterBegin + rand() % (iterEnd - iterBegin));
                ++iterBegin;
            }
        }

然后再进入main():

int main()
{
    //container used as to apply algorithm to.
    list<int> List = {34,77,16,2,35,76,18,2};

    //randomize example.
    cout << "calling randomize on sorted vector: " << endl;
    List.sort();
    vector<int> temp(List.begin(), List.end());
    cout << "before randomize: " << endl;
    for (vector<int>::iterator it = temp.begin(); it != temp.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;

    randomize(temp.begin(),temp.end());
    cout << "after randomize: " << endl;
    for (vector<int>::iterator it = temp.begin(); it != temp.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl<<endl;
    return 0;
}

我有几个问题:

  1. 我相信执行iterEnd-iterBegin(如模板功能所示)是有效的操作,因为iterEnd和iterBegin都是C ++样式指针。减去这些指针可得出它们之间的距离。我说得对吗?

  2. 我在即时窗口中尝试了以下操作:

iterEnd
{-33686019}
    [ptr]: 0x00ba4f78 {-33686019}
    [Raw View]: {...}

表示iterEnd是一个指针,其值为0x00ba4f78,它指向-33686019的垃圾值。我相信这里是正确的吗?

因此,迭代器是一个指针,用于随机访问迭代器。所有迭代器类型(输入/输出迭代器,正向迭代器,双向迭代器)是否都正确?如果这些迭代器不是C ++样式的指针,那是什么?

  1. 我还在即时窗口中尝试了以下操作:
&iterEnd
0x006ff368 {-33686019}
    [ptr]: 0x00ba4f78 {-33686019}
    [Raw View]: 0x006ff368 {...}
&&iterEnd
expected an expression

为什么&iterEnd给我一个地址?它应该给我消息“期望表达式”,就像&& iterEnd一样。

  1. 如何实现随机访问迭代器? -我问是因为iterEnd给了我一个指针值,&iterEnd也给了我一个(不同的)指针值。随机访问迭代器是指针中的指针吗?

1 个答案:

答案 0 :(得分:3)

对于随机访问迭代器(矢量迭代器),迭代器为C ++ 样式指针?

简短的回答-取决于编译器。

vector迭代器的内部是实现定义的。 std::vector<T>::iterator可能有operator -重载,因此它给指针减法带来了错觉。因此,如果您假设vector迭代器是简单的指针,则使用各种编译器会破坏假定它们是简单的指针的代码的编写,而对于其他编译器,它将成功编译。

其中一个著名的例子是Visual C ++,其中在6.0版中,vector迭代器是简单的指针,因此当时使用该编译器的许多作者都会在假设std::vector<T>::iterator只是代码的情况下编写代码。 T*。由于向量迭代器被实现为指针,因此代码成功编译并正常工作。

一个例子就是这样:

#include <vector>

void foo(char *c)
{
}

int main()
{
   std::vector<char> vc;
   foo(vc.begin());
}

没有编译错误,因为vc.begin()是一个简单的char *

然后是Visual C ++的后续版本,而以前在6.0下成功编译的代码现在被破坏了。 std::vector<T>::iterator不再是简单的T*,而是struct。对于Visual C ++> 6.0版,必须更改很多基于迭代器(错误)推理(简单指针)的代码。