在数组上使用迭代器

时间:2014-05-08 13:33:20

标签: c++ arrays pointers c++11 iterator

C++ Primer中陈述

  

在C ++中,指针和数组紧密交织在一起。尤其如此   我们将看到,当我们使用数组时,编译器通常会转换   数组到指针

我想使用迭代器来打印数组。下面的程序工作正常,但是当我尝试打印arr2arr3时,如果我没有弄错,类型为int *,我会收到错误(判断为&运算符意味着参考下面)。

  

error: no matching function for call to ‘begin(int*&)’

int main(int argc, char** argv) {

    int arr[] = {0,1,2,3,4,5,6,7,8,9};
    auto arr2 = arr;
    auto arr3(arr);   // I think arr2 and arr3 are of same type

    for(auto it = std::begin(arr) ; it != std::end(arr) ; ++it)
        std::cout << *it << " ";
    std::cout << std::endl;

    return 0;
}

考虑到该语句,如果编译器将数组转换为指针,则该程序如何使用arrstd::begin()打印std::end()的内容,并且不适用于arr2arr3如果所有这些都是整数的指针?


修改

如果我无法说清楚,我很抱歉。我希望我能通过这次编辑澄清问题。

现在我知道begin()end()不能使用指针(感谢答案),我想知道引用的文本是不是真的,因为它指定有一个数组 - &gt;指针转换。如果文本说的是真的那么arr的类型应该是指针。此时引用的文字是否有问题?

另外,有没有什么方法可以使用begin()end()指定大小(而不是STL容器),可能使用以下构造函数?

template< class T, size_t N > 
T* begin( T (&array)[N] );

4 个答案:

答案 0 :(得分:7)

数组很容易转换为指针,但并非总是如此。例如,如果您获取数组的地址或获取引用,则原始数组类型不会丢失:

int a[10];
int (&ar)[10] = a; // fine
int (*ap)[10] = &a; // also fine

但是,当您以一种大多数其他类型将被复制的方式使用数组时,数组将转换为指针,而是复制指针。

在您的示例中,如果您将其作为参考,则可以使用arr2:

 auto &arr2 = arr;

现在arr2的类型为int (&)[10],而不是int *

答案 1 :(得分:2)

因为std::begin是为数组定义的,而不是为指针定义的。数组类型与指针类型不同。

这里的问题是显然auto arr2 = arr会将类型从数组类型降级为指针类型。

请注意,问题实际上是std::end而不是std::begin。毕竟,std::end如何能够将指针指向最后的+ 1元素,当它所有的元素都是指向第一个元素的指针时?它不能,因此无法为指针类型定义std::end,因此std::begin对指针类型没有任何意义。

准确地说,arr的类型为int[10],而arr2arr3的类型为int*。前者可以降级为后者,但反之亦然。

答案 2 :(得分:2)

此处,auto会将arr(数组类型)衰减为指针。 std::beginstd::end只能用于容器或数组,但不能用于指针。

来自C ++ 11标准

  

§7.1.6.4自动说明符 [dcl.spec.auto]

     

1 auto类型说明符表示声明的变量类型应从其初始化程序中推导   或者函数声明符应包含尾随返回类型。

您的代码无法在此处运行,因为auto无法推断出数组类型。就像:

char a[5];
auto b[5] = a;  // error, a evaluates to a pointer, which does
                // not match the array type

要使其正常工作,只需使用std::vector之类的C ++容器:

vector<int> arr = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

答案 3 :(得分:1)

std::beginstd::end使用C样式数组的参数。

std::end的可能实现是:

template<class T, std::size_t sizeOfArray>
constexpr T *end(T (&array)[sizeOfArray])
{
  return &array[sizeOfArray];
}

这种方式arr在调用std::end(arr)时不会在指针中转换(并且有关数组大小的信息不会丢失......该函数只接受精确的数组sizeOfArray个元素作为参数)。

template<class T>
T *end(T array[])
{
  // ?
}

由于T array[]在用作函数参数时表现得像平面指针(T *array)而不是真正的数组,所以

无法工作。

auto将数组arr衰减为指针,技巧不再有效。