为什么std :: accumulate的行为与标准数组一样?

Jam*_*bri 11 c++ arrays pointers c++11

我刚刚进入C++,我认为我有一个指针,但std::accumulate()让我感到困惑.

鉴于阵列:

int a[3] = { 5, 6, 7 };
Run Code Online (Sandbox Code Playgroud)

我想将数组的值加起来std::accumulate(),所以我将它传递给第一个元素,然后是最后一个,然后是累加器的起始值.

std::accumulate(a, a + 2, 0);
std::accumulate(&a[0], &a[2], 0);
Run Code Online (Sandbox Code Playgroud)

糟糕:其中任何一个都只返回前两个元素的总和:11.

另一方面,如果第二个参数是一个荒谬的指针,只是超出范围......

std::accumulate(a, a + 3, 0);
std::accumulate(&a[0], &a[3], 0);
Run Code Online (Sandbox Code Playgroud)

... 18返回正确的值.

有人可以解释一下吗?我意识到我可以避免使用简单的数组,但这不是重点.

Xar*_*arn 20

C++范围被定义为[first, last),并且所有STL算法都是这样工作的.在这种情况下,std::accumulate总结迭代器定义的范围后面的所有元素,从开始到first结束last而不实际解除引用它.

因此,调用它std::accumulate(a, a+3, 0)实际上是正确的,等于调用它std::accumulate(begin(a), end(a), 0).

还要注意,这并没有违反"没有指向已分配数组之外的指针"规则,因为指向最后一个元素后面的指针有一个特定的异常.

  • 这对于处理您想要对零​​元素进行操作的退化情况是必要的.对于超出最后一个元素的指针有一个特殊的例外,但对于第一个元素前面的指针没有这样的例外. (3认同)

Pra*_*han 5

std::accumulate和大多数STL算法一样,它使迭代器超过容器的最后一个元素.在这种情况下,迭代器将是&a[3].您可能想要使用std::begin(),std::end()因为它适用于所有容器,并且不易出错.此外,因为std::begin在数组上只是一个指针,你总能说出类似的东西std::begin()+k.所以,你不会失去任何灵活性.