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

C++ 为什么这样的迭代器是合法的?,c++,arrays,c++11,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; } #包括 inta[]={1,2,3,4,5}; int main() { 对于(int i:a) printf(“%d\n”,i); 返回0; } 在我看来,for(inti:a)只在a是整数向量时有效。但在上面的代码中,a是

这是密码

#include <stdio.h>

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

int main()
{
    for (int i : a)
        printf("%d\n", i);
    return 0;
}
#包括
inta[]={1,2,3,4,5};
int main()
{
对于(int i:a)
printf(“%d\n”,i);
返回0;
}

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

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

在我看来,for(inti:a)只在a是整数向量时有效

你错了

在上面的代码中,a是一个整数数组,非常类似于指向整数的指针

你在这里也错了。数组和指针是两种完全不同的东西

为什么这样做有效


因为这就是Range所做的。它在容器上迭代。数组是一个容器。

编译器知道它需要知道的关于该数组的一切

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


数组不是指针,为了更好地理解这个问题,你可以从不同的角度来解决这个问题,例如你应该理解,当你把数组传递给一个函数,实际上你在C和C++中解决了一个不能被很好地解决的问题时,没有<代码>无效FO(t ARR[])< />但是您必须使用void foo(T*arr),因为您无法创建一个仅在C/C++中使用数组的真正接口。

如其他答案中所述,数组不是指针。在某些上下文中,它们衰减为指针,这是事实,但仅在某些上下文中

int a[] = {1, 2, 3, 4, 5};
a
的类型是
int[5]
,一个包含五个
int
类型元素的数组。在本例中,一对空方括号告诉编译器推断元素的数量,因此您的定义相当于
inta[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;
}
总而言之:
T[N]
是一种类型:具有
N
类型
T
元素的数组
N
是编译时已知的一个整数常量,因此编译器知道数组的最后一个元素在哪里,因此能够生成一个循环,循环遍历所有元素


如果您想了解更多关于数组衰减的信息,我建议您阅读。

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

模板
内联*
开始(_-Tp(&u-arr)[[u-Nm])
{return\uuu arr;}
模板
内联*
结束(_-Tp(&u-arr)[_-Nm])
{返回uu arr+_Nm;}

<代码> > p>因为编译器尊重C++标准。草案n4296明确指出,基于范围的for语句对普通数组有效:

6.5.4基于语句的范围[stmt.ranged] 对于窗体的基于范围的For语句

for ( for-range-declaration : expression ) statement

(1.1)-如果_range是数组类型。。。。如果_range是大小未知的数组或 类型不完整,程序格式不正确


inta[]={1,2,3,4,5}定义了一个由5个整数组成的数组。

请检查:这是一个相当奇怪的问题。假设一段代码表现完美,然后假设它不应该因为一个假设而表现完美。“为什么它能工作”的答案显然是“假设是错误的”,因为编译器总是比你更清楚!你为什么不调查这个错误的假设?为什么它不起作用?你为什么不想让它工作?“因为你不能创建一个只有C/C++的数组的真正接口。”——技术上是正确的,因为没有“C/C++”这样的东西。但是你可以在C++中创建这样的接口。但是你可以使用<代码>模板无效的fo(t(& ARR)[n]){} /Calp> @ SergBaleLista是的,它是有效的,而上面的代码就是它的工作原理。
{
    auto && __range = a; 
    for (auto __begin = a, __end = a + 5; __begin != __end; ++__begin)
    {
        int i = *__begin; 
        std::printf("%d\n", i);
    }
}
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; }
for ( for-range-declaration : expression ) statement