0

我对指针和迭代器不是很清楚,尤其是在从数组构造向量的情况下。

从关于vector的描述中,它说

// the iterator constructor can also be used to construct from arrays:
int myints[] = {16,2,77,29};
std::vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );    

主要是:

#include <vector>

int arr[ARR_LEN] = { /* Array elements */ };
std::vector<int> vecInt(arr, arr + ARR_LEN);

它使用以下构造函数吗?

template <class InputIterator>
vector (InputIterator first, InputIterator last,
        const allocator_type& alloc = allocator_type());

如果是这样,那么这里是否将指针(用于数组)处理为随机访问迭代器,然后作为输入迭代器?编译器如何做到这一点?考虑来自其他容器的迭代器,这个迭代器的类型是什么,例如“array[int]”::iterator?

int arr[N] = {};
for (int i= 0; i<N; i++) {}

而不是上面的,我可以做如下的事情吗?

for (ItorType it=arr; it!=arr+N; ++it) { ... }
4

4 回答 4

5

迭代器模板参数不是特定的类。事实上,这些名称对编译过程没有真正的影响。相反,它们指的是特定概念,这些概念指定了特定迭代器可用的方法。任何 RandomAccessIterator 也必须是 InputIterator:RandomAccessIterator 概念是 InputIterator 概念的改进。

编译器实际上只是通过这些参数,在你的情况下是指针。指针实现了 RandomAccessIterator 概念,即它们可以很容易地与std::vector<...>您引用的构造函数一起使用。顺便说一句,编写此初始化的正确方法是

std::vector<int> vecInt(std::begin(arr), std::end(arr));

函数模板begin()end()添加到最新版本的 C++ 中,并推断出静态数组的大小。在您的示例中用于确定大小的两种方法在某些方面都有问题。

于 2013-09-27T14:26:05.693 回答
2

它使用以下构造函数吗?

是的。

如果是这样,那么这里是否将指针(用于数组)处理为随机访问迭代器,然后作为输入迭代器?

是的。

编译器如何做到这一点?

诸如此类的概念InputIterator是类型必须如何表现的非正式规范;要成为一个InputIterator,它必须支持间接 ( *it) 来访问一个值,并支持递增 ( ++it)it++来移动到下一个值。要成为 a RandomAccessIterator,它必须支持这些操作,再加上一些额外的操作,例如加法和减法。指针满足这些要求,因此可以在需要迭代器的任何地方使用。

考虑来自其他容器的迭代器,这个迭代器的类型是什么,例如“array[int]”::iterator?

您将使用指针 ,int*来遍历数组 , int[]。当用作函数参数(如此处)或用于算术(如arr+N)时,数组会自动转换为指向其第一个元素的指针。

而不是上面的,我可以做如下的事情吗?

是的。ItorType将是相应的指针类型,int*. 在 C++11 中,我们有beginend函数来获取任何范围的开始和结束,包括数组:

for (auto it = std::begin(arr); it != std::end(arr); ++it)

还有基于范围的循环:

for (int i : arr)
于 2013-09-27T14:29:47.200 回答
1
template <class InputIterator>
vector (InputIterator first, InputIterator last,
        const allocator_type& alloc = allocator_type());

编译器将使用此构造函数,因为它是两个参数的构造函数,两个参数的类型相同。

参数不一定是迭代器。例如,如果你写

vector<int> x(3.0, 1.0);

编译器将尝试使用相同的构造函数(这会导致编译错误,因为不能像迭代器一样使用双精度)。

于 2013-09-27T14:23:46.190 回答
1

是的,它使用上述构造函数并将指针视为随机访问迭代器。因为所有的 RandomAccessIterators 也是 InputIterators(见这里)。编译器可以这样做,因为迭代器类根据静态接口在其自身上定义了有效的运算符。无论他们如何实施和实际意味着什么。只有类型正确性和接口正确性才能发挥作用。

您可以typedef int * ItorType并且您的最后一个示例将编译并运行得很好。

于 2013-09-27T14:26:49.650 回答