为什么这样的迭代器合法?

时间:2016-03-05 02:59:37

标签: c++ arrays c++11

这是代码

#include <stdio.h>

int a[] = {1, 2, 3, 4, 5};

int main()
{
    for (int i : a)
        printf("%d\n", i);
    return 0;
}

在我看来,对于(int i:a),只有当a是整数向量时才有效。但是在上面的代码中,a是一个整数数组,很像一个指向整数的指针。为什么这样做?

6 个答案:

答案 0 :(得分:13)

数组“非常像指针”。数组可以衰减为指针,但在非衰减的上下文中,它仍然是一个已知大小的数组。

答案 1 :(得分:3)

如其他答案所述,数组不是指针。它们在某些情况下会衰减成指针,这是正确的,但仅限于某些情况下。

int a[] = {1, 2, 3, 4, 5};

a的类型为int [5],这是一个包含五个int类型元素的数组。在这种情况下,一对空方括号告诉编译器推导出元素的数量,因此您的定义等同于int a[5] = {1, 2, 3, 4, 5};

如果您仍然不相信,这里有一段代码试图让编译器发出包含a类型的错误消息:

template <typename T> struct Type;

int main()
{
    int a[] = {1, 2, 3, 4, 5};
    Type<decltype(a)> dummy;
}

g ++ 5.3发出

error: aggregate ‘Type<int [5]> dummy’ has incomplete type and cannot be defined

如您所见,decltype(a)为int [5]

cppreference.com包含range-based for loop的详细说明。 你的for循环相当于:

{
    auto && __range = a; 
    for (auto __begin = a, __end = a + 5; __begin != __end; ++__begin)
    {
        int i = *__begin; 
        std::printf("%d\n", i);
    }
}

总结一下:T [N]是一种类型:N类型为T的元素的数组。 N是编译时已知的整数常量,因此编译器知道数组的最后一个元素的位置,因此能够生成一个遍历所有元素的循环。

如果您想了解有关阵列衰减的更多信息,建议您阅读What is array decaying?

答案 2 :(得分:1)

编译器知道有关该数组的所有知识

T arr[]

是一种不完整的类型,但它会变得更好并且“#34”功能完整&#34;右边的部分是一个列表,一个定义大小的列表,在编译时编译器已知,所以它是静态检查的,你有它,你知道大小,你甚至知道元素;你还需要什么?

顺便说一下,数组不是指针,为了更好地理解你可以从不同角度解决这个问题,例如你应该明白,当你将一个数组传递给一个函数时,你实际上是在解决一个无法解决的问题。在C和C ++中可以很好地解决,没有void foo( T arr [] ),但是你被迫使用void foo ( T * arr ),因为你无法在C / C ++中创建一个只有数组的真实接口。 / p>

答案 3 :(得分:0)

  

在我看来,对于(int i:a),仅当a是整数向量

时才有效

你错了。

  

在上面的代码中,a是一个整数数组,它非常像指向整数

的指针

你也错了。数组和指针是两个完全不同的东西。

  

为什么这样做?

因为那是什么范围。它遍历容器。数组是容器。

答案 4 :(得分:0)

因为它调用了std::begin()std::end(),它专门用于C数组。这是来自glibc的<range_access.h>

template<class _Tp, size_t _Nm>
inline _Tp*
begin(_Tp (&__arr)[_Nm])
{ return __arr; }

template<class _Tp, size_t _Nm>
inline _Tp*
end(_Tp (&__arr)[_Nm])
{ return __arr + _Nm; }

答案 5 :(得分:0)

因为编译器遵循C ++标准。草案n4296明确表示基于范围的for语句对普通数组有效:

  

6.5.4基于范围的语句[stmt.ranged]

     

对于基于范围的表格形式

for ( for-range-declaration : expression ) statement
     

...
  (1.1) - 如果_RangeT是一个数组类型....如果_RangeT是一个未知大小的数组或一个数组   不完整的类型,程序是不正确的;

int a[] = {1, 2, 3, 4, 5};定义了一个包含5个整数的数组。