C++ 标准是否对在空容器上运行的算法有任何保证?
Does the C++ standard guarantee anything about algorithms operating on empty containers?
例如,
#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
我能保证这种行为会发生在任何符合标准的编译器上吗?
由于标准库算法在迭代器范围上运行,算法保证在传递给它们的任何有效迭代器范围上都是安全有效的.现在我们只需要关心有效的迭代器范围代表什么。
对形成迭代器范围的迭代器的要求:
- 它们必须引用元素(或最后一个元素之后的元素)
同一个容器
- 可以通过重复递增
begin
达到end
。在
换句话说,end
不能在 begin
. 之前
满足这些要求后,我们可以将任何有效范围视为左包含范围:[begin, end)
。那么该范围具有以下属性:
- 如果
being
等于end
,范围为空
- 如果
begin
不等于 end
,则至少有一个元素
范围,being
指的是第一个元素
- 所以,我们可以增加
begin
一些次数,直到begin == end
(发生这种情况时,范围仍然有效)
正是这些属性为迭代器的便捷使用提供了支持。 <algorithms>
内部结构也基于这些属性。
我们必须知道编译器无法强化这些要求,我们要确保传递范围的有效性(有时有相当多的需要考虑的几个因素).
所以,是的,当传递给算法时,begin == end
仍然是一个有效范围,所以我们得到的输出也是有效的。
例如,
#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
我能保证这种行为会发生在任何符合标准的编译器上吗?
由于标准库算法在迭代器范围上运行,算法保证在传递给它们的任何有效迭代器范围上都是安全有效的.现在我们只需要关心有效的迭代器范围代表什么。
对形成迭代器范围的迭代器的要求:
- 它们必须引用元素(或最后一个元素之后的元素) 同一个容器
- 可以通过重复递增
begin
达到end
。在 换句话说,end
不能在begin
. 之前
满足这些要求后,我们可以将任何有效范围视为左包含范围:[begin, end)
。那么该范围具有以下属性:
- 如果
being
等于end
,范围为空 - 如果
begin
不等于end
,则至少有一个元素 范围,being
指的是第一个元素 - 所以,我们可以增加
begin
一些次数,直到begin == end
(发生这种情况时,范围仍然有效)
正是这些属性为迭代器的便捷使用提供了支持。 <algorithms>
内部结构也基于这些属性。
我们必须知道编译器无法强化这些要求,我们要确保传递范围的有效性(有时有相当多的需要考虑的几个因素).
所以,是的,当传递给算法时,begin == end
仍然是一个有效范围,所以我们得到的输出也是有效的。