C++标准是否对操作空容器的算法做出了任何保证?

3

例如,

#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

int main() {
  std::vector<int> empty{};
  std::reverse(empty.begin(), empty.end());
  std::cout << "Sum: " << std::accumulate(empty.cbegin(), empty.cend(), 0) << std::endl;
  std::cout << empty.size();
}

按我的期望构建并运行:

sum: 0
size: 0

我能否保证这种行为在任何符合标准的编译器上都会发生?


1
正是像这样的部分保证了空集的行为。 - NathanOliver
1个回答

6

由于标准库算法操作的是迭代器范围,所以算法在任何有效的迭代器范围上都是安全和有效的保证。现在我们只需要关注什么是有效的迭代器范围。

形成迭代器范围的迭代器要求:

  • 它们必须引用相同容器的元素(或最后一个元素之后)
  • 可以通过重复递增begin来到达end。换句话说,end不能在begin之前。

满足这些要求后,我们可以将任何有效范围视为左包含范围[begin,end)。因此,该范围具有以下属性:

  • 如果being等于end,则该范围为空
  • 如果begin不等于end,则范围中至少有一个元素,并且begin指向第一个元素
  • 因此,我们可以将begin递增若干次,直到begin == end(当发生这种情况时,范围仍然有效)

正是这些属性为迭代器的方便使用提供了支持。 <algorithms>内部也基于这些属性。

我们必须意识到编译器无法强制执行这些要求,我们需要确保传递的范围的有效性(有时需要考虑相当多的因素)

因此,是的,当传递给算法时,begin == end仍然是一个有效的范围,因此我们得到的输出也是可以预期的。


1
在容器为空的情况下,begin == end,因此通过将begin增加零次可以到达end。因此,暗示空容器是STL算法的有效操作数吗? - segfault
@segfault请检查最新的编辑,我猜它回答了这个问题。另外,如果我们尝试思考如何实现一个算法,我们肯定会在其中加入类似于begin != end的东西。 - rawrex
@segfault 当且仅当两个迭代器都指向同一个容器并且 b 没有超出 e 的范围时,该范围才是有效的,也就是说 b==e 仍然是有效的。 - rawrex

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