为什么标准不允许std :: for_each在无效的随机访问迭代器范围上有明确定义的行为?

时间:2012-02-07 09:52:41

标签: c++ stl foreach iterator range

在这个 question 中,有人解释说,当给定无效的迭代器范围[first,last]时,std :: for_each具有未定义的行为(即,当通过先递增时无法到达last时)。

大概这是因为一般循环for(auto it = first; it != last; ++it)将永远在无效范围上运行。但对于随机访问迭代器,这似乎是一个不必要的限制,因为随机访问迭代器有一个比较运算符,可以将显式循环写为for(auto it = first; it < last; ++it)。这会将无效范围内的循环转换为无操作。

所以我的问题是:为什么标准不允许std :: for_each在无效的随机访问迭代器范围内有明确定义的行为?它将简化几种算法,这些算法仅对多元素容器有意义(例如,排序)。使用运算符&lt;()而不是operator!=()?

是否存在性能损失

3 个答案:

答案 0 :(得分:4)

  

这会将无效范围上的循环转换为无操作。

情况不一定如此。

无效范围的一个示例是firstlast引用不同的容器时。比较这些迭代器将导致至少some cases中的未定义行为。

答案 1 :(得分:2)

因为这是一般政策。所有使用<都是允许的 像:

std::for_each( v.begin() + 20, v.begin() + 10, op );

即使使用<,也传递无效的迭代器或来自不同的迭代器 容器,是未定义的行为。

答案 2 :(得分:2)

  

这会将无效范围上的循环转换为无操作。

您似乎在说operator<应始终返回false两个随机访问迭代器,这些迭代器不属于同一范围。这是你指定的循环是无操作的唯一方法。

指定此标准没有意义。请记住,指针是随机访问迭代器。考虑指针操作的实现负担,以及引起读者的一般混淆,如果定义以下代码打印“两个”:

int a[5];
int b[5]; // neither [a,b) nor [b,a) is a valid range
if ((a < b) || (b < a)) {
    std::cout << "one\n";
} else {
    std::cout << "two\n";
}

相反,它是未定义的,因此人们不会在第一时间写它。