Bre*_*ren 5 c++ arrays foreach for-loop
我在http://www.cplusplus.com/doc/tutorial/arrays/上查看以下示例,我无法弄清楚第二个for循环是如何工作的.for循环如何知道数组何时结束.如果它能弄明白为什么第一个循环不使用类似的方法?我的印象是无法确定阵列的长度.我不确定如何调和这些观念.谢谢!
编辑:感谢所有的好答案!
#include <iostream>
using namespace std;
int main()
{
int myarray[3] = {10,20,30};
for (int i=0; i<3; ++i)
++myarray[i];
for (int elem : myarray)
cout << elem << '\n';
}
Run Code Online (Sandbox Code Playgroud)
这个工作的原因是for有效的循环1使用std::begin和std::end.反过来,这些工作,因为它们专门为内置数组提供重载,如下所示:
template <class T, size_t N>
T *begin(T (&array)[N]) {
return array;
}
template <class T, size_t N>
T *end(T (&array)[N]) {
return array+N;
}
Run Code Online (Sandbox Code Playgroud)
虽然它(显然)在原始(1998)C++标准发布之前尚未实现,但该技术不需要除C++ 98中提供的任何语言功能之外的任何语言功能.C++ 11编写了这项技术并将其付诸实践.
因为在这种情况下,参数被指定为对数组的引用,所以只有当参数确实是一个数组时,类型推导才会成功.在这种情况下std::begin,还有一些版本支持其他参数类型并使用(例如)集合begin()和end()成员,如果匹配该类型.
1."有效",在这种情况下,这意味着有一些情况,其中范围为基础的循环使用begin和end,和其他人在他们没有.如果你是技术人员,他们不是用于数组,但直接完成类似的计算.同样,对于具有begin和end成员的容器类型,直接使用它们.如果这两个时间都不是真的,那么begin(range)和end(range)被使用,这可以使用std::begin/ std::end或begin(x)/ end(x)由参数依赖查找发现对.
您有一个误解,认为 range-for 需要提前知道迭代次数(“长度”)。它不是。
它确实需要一个终止条件,其形式为it != __endwhere__end = x.end()或__end = end(x)。
当然,数组不能改变它们的大小,因此在这种情况下,检测结束和知道长度是等效的(长度可以通过开始、结束和指针减法获得)。
正如 Oli 在评论中提到的,数组的类型确实包含长度信息,并std::end使用数组引用作为其参数,以避免指针衰减而丢失此信息。
定义基本上是:
namespace std
{
template<typename T, size_t N>
T* end(T (&array)[N])
{
return array + N;
// or if you want to be cute
// return 1[&array];
}
}
Run Code Online (Sandbox Code Playgroud)
当数组引用中的绑定是非类型模板参数时,它是可推导的。在编写接受数组的函数时,可以利用这一点。
(编译器实际上array + N内置了数组末尾的计算,但它并不用于std::end()此目的。但是无论如何内联后都没有区别,了解如何发挥编译器所做的相同技巧是很有用的。 )