C++11的范围for循环如何知道数组的大小?

9

当我做类似这样的事情:

int my_array[5] = {1, 2, 3, 4, 5};
for (int &x : my_array) {
    x *= 2;
}

C++11显然知道我的数组只有5个元素,这些信息是否存储在my_array对象中?

如果是的话,为什么不能向开发人员提供这些信息呢(或者可以吗?!?)?如果C ++开发人员始终知道他们正在处理的数组的界限,那么很多世界性的问题似乎会得到解决。

3个回答

11

这只是语言工作所需的东西,编译器必须实现。显然,my_array 的完整类型为 int[5] (即大小是 类型 的一部分),因此此信息readily可用。

与普遍认为的相反,在 play 中没有使用免费的 std::begin()/std::end() 函数,尽管那些函数表面上似乎能够完成任务(但涉及到 ADL 的问题会破坏此方法)。


好的。那么为什么my_array.size不存在呢? - MrFox
6
еҪ“然пјҢеӣ дёәж•°з»„дёҚжҳҜзұ»зұ»еһӢпјҢжүҖд»ҘдёҚиғҪе…·жңүжҲҗе‘ҳеҮҪж•°гҖӮдҪҶжҳҜдҪ еҸҜд»ҘиҪ»жқҫең°зј–еҶҷдёҖдёӘarray_sizeиҮӘз”ұеҮҪж•°жЁЎжқҝжқҘдә§з”ҹжүҖйңҖзҡ„еҖјпјҢжҲ–иҖ…дҪҝз”ЁзҺ°жҲҗзҡ„std::extentгҖӮ - Kerrek SB
我怎么能够不知道这个东西而活了这么久... 我要怪罪std::vector :)。 - MrFox
3
因为std::extent也是C++11新的东西。这些机制(数组类型作为类型的一部分)并不新鲜,所以一直都可以编写std::extent。只是直到最近才开始使用它。 - Nicol Bolas

6

它是可用的 - 在标准C++中,您可以定义数组上的beginend。数组的大小已编码在类型中。

一般的方法是使用对数组的引用。

这里是一个示例大小函数:

template<typename T, size_t N>
size_t array_size(T (& const)[N])
{
    return N;
}

6
这也被称为std::extent。而且,标准库中已经为数组定义了 std::beginstd::end - Kerrek SB

5
不是对象的一部分,但是它是类型的一部分。这就是数组声明中的5。 然而,以下代码行不起作用:
void f(int arr[5]) {
    for(int& x: arr) {
        // whatever
    }
}

因为这里数组的名称会衰变为指向其第一个元素的指针,也就是说,参数声明相当于 int *arr,它没有大小信息。

3
在这种情况下,我不会使用“decay”这个术语。我认为该术语通常适用于许多表达式中对数组变量进行的隐式转换。int a[5]; a + 1; // decay 相反,我喜欢用术语“adjust”来描述这里发生的情况,因为这是标准使用的词语。void foo(int a[5]); // type 'adjustment': equivalent to void foo(int *a)。我在说这个单词时喜欢使用讽刺的语气。 - bames53
作为参考,@balki的解决方案无法处理大小未知的数组引用,例如(&arr)[5]。但是,通常可以通过使用数组大小作为模板参数来使其适用于通用大小的数组:请参见https://dev59.com/218e5IYBdhLWcg3wAWns。 - andybuckley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接