2013-03-05 77 views
1

我知道下面的代码可以从阵列构建STL向量:std :: vector构造函数 - 为什么int而不是int *?

// 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)); 

(来源:cppreference

使用的构造应是

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

如果<类InputIterator的>< int>在上面的例子中,为什么不是InputIterator第一个是一个整数指针吗?数组名“myints”衰变成一个指向第一个元素,因为它相当于& myints [0]

我想到了一个正确的版本将是

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

在你的情况下,'InputIterator'是'int *'。 – PlasmaHH 2013-03-05 10:04:11

+1

迭代器不是指针。指针可以对迭代器概念进行建模,但其他方式不能以任何方式保证。 – Xeo 2013-03-05 10:05:41

回答

6

std::vector声明是这样的:

template <class T, class Allocator = std::allocator<T>> 
class Vector 
{ 
    // ... 
    typedef Allocator allocator_type; 

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

    // ... 
}; 

请注意,类本身和构造函数都有模板参数。当您创建std::vector<int>时,int模板参数用于类模板参数T,确定向量的元素类型,而不是构造函数的InputIterator

您允许编译器推导InputIterator(事实上,必须推导出构造函数的模板参数)。您正在传递myints作为将要推断出InputIterator的函数的第一个参数。由于myints衰减到int*到你的数组的第一个元素,就像你说的,然后InputIterator会被推断为一个int*,你会得到构造以下实例:

vector (int* first, int* last, 
     const allocator_type& alloc = allocator_type()); 

InputIterator不是推断为int。它被推断为您作为第一个参数传递的完整类型(当然,第二个参数必须匹配)。

这很有道理,因为int不是有效的输入迭代器。无论推导InputIterator是否必须满足输入迭代器的要求。然而,int*是有效的。

+1

只有两点意见:对于类型扣除的工作,“first”和“last”必须推导出相同的类型。 (他们都是'int *',但值得指出)。第二,如果你写了'std :: vector v(10,42);',它也是这个构造函数被选中的。标准中有特殊的语言,如果'InputIterator'被推导为整型(这里是'int'),那么构造函数必须像第一个参数的类型为size_t而不是int。 – 2013-03-05 10:25:18

0

<class InputIterator>不能为<int>,因为您无法取消引用(应用operator*()int

+0

他的观点是,签名提起了'InputIterator *',它可以被解除引用。 – PlasmaHH 2013-03-05 10:07:26

4

您将模板类型的向量(您的案例中的int)与构造函数参数的模板化类型混淆。 std::vector<T>的构造函数采用第一个参数InputIterator -yielding- T

即 - <class InputIterator>不是int;它是一个迭代器,取消引用int;如int*

1

这是因为迭代器并不总是指针。或者换句话说:大多数迭代器都是而不是指针,因此您提出的签名不适用于它们。

所以在你的情况下,InputIteratorint*这是完全可以理解的,因为迭代器的概念最初是作为“指针范围”的一个更广泛的概念发明的。

相关问题