是否定义为C ++标准算法提供反转范围?

时间:2011-09-21 18:40:56

标签: c++ c++11 std

考虑标准算法,例如std::for_each

template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f);

据我所知,实际上并没有要求两个InputIterator参数的相对状态。

这是否意味着以下技术上有效?还是未定义?我可以实际期望做什么

std::vector<int> v{0,1,2,3,4};
std::for_each(
   v.begin()+3,  // range [3,0)
   v.begin(),
   [](int){}
);

geordi告诉我:

  

错误:函数需要有效的迭代器范围[__ first,__last)。 [+ 13废弃的行]

但我不知道这个调试诊断是否合规。


在尝试迂腐确定如何定义以下行为时,我想出了这个问题:

std::vector<int> v; // <-- empty
std::for_each(      // <-- total no-op? stated or just left to implication?
   v.begin(),
   v.end(),
   [](int){}
);

5 个答案:

答案 0 :(得分:21)

标准明确要求last迭代器可以从first迭代器到达。这意味着通过递增first,最终应该能够点击last

  

24.1迭代器要求

     

...

     

6 迭代器j从迭代器i调用,当且仅当   表达式++i的应用程序有限   制作i == j。如果可以从j访问i,则表示相同   容器。

     

7 大多数库的算法模板都在运行   数据结构上有使用范围的接口。范围是一对   指定计算开始和结束的迭代器。   范围[i, i)是一个空范围;通常,范围[i, j)指的是   数据结构中的元素以指向的元素开头   i,但不包括j指向的那个。范围[i, j)是   当且仅当j可以从i访问时有效。结果   将库中的函数应用于无效范围是   未定义。

答案 1 :(得分:6)

结果为未定义。


C ++ 03标准:25.1.1每个
C ++ 11标准:25.2.4对于每个 陈述:

template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f);
  

1效果:将f应用于取消引用[first,last]范围内的每个迭代器的结果,启动   从第一个开始到最后一个 - 1

另一部分将有效范围[first,last)定义为:

C ++ 03标准:24.1迭代器要求
C ++ 11标准:24.2.1迭代器要求

两者的

第7段

  

在数据结构上运行的大多数库的算法模板都有使用range的接口。范围是一对指定计算开始和结束的迭代器。范围[i,i]是空范围;通常,范围[i,j]是指数据结构中的元素,从i指向的那个开始,直到但不包括j指向的元素。 当且仅当j可从i到达时,范围[i,j]才有效。将库中的函数应用于无效范围的结果未定义。


记得在某个地方读过这篇文章,只是浏览过:

C ++标准库 - 教程和参考 - 作者Nicolai Josutils

这在以下内容中提到:

  

5.4.1范围
  调用者必须确保第一个和第二个参数定义有效范围。如果通过遍历元素从一开始就可以到达,那么就是这种情况。 这意味着,程序员必须确保两个迭代器都属于同一个容器,并且开头不在末尾。如果不是这种情况,则行为未定义,可能导致无限循环或禁止内存访问

答案 2 :(得分:2)

  

这是否意味着以下技术上有效?或者是它   未定义?我可以实际期望它做什么?

不,不是。当for_each递增迭代器并且迭代器指向end时,您的代码将显示未定义的行为,并且没有任何内容可以取消引用(嗯,此时它足以获得未定义的行为,所以有没有必要谈论过去的结局)!

答案 3 :(得分:2)

标准的第24.1节“迭代器要求”对此进行了解释:

  

迭代器j从迭代器i被称为可到达当且仅当表达式++i的应用程序的有限序列{ {1}}。如果i == j可以从j访问,则它们会引用同一个容器。

     

...

     当且仅当i可以从[i, j)访问时,

范围j才有效。将函数库中的函数应用于无效范围的结果是未定义的。

所以i可以从v.begin() + 3到达,但不能相反。因此v.begin()不是有效范围,您对[v.begin()+3, v.begin())的调用未定义。

答案 4 :(得分:1)

该标准定义了采用范围的函数的复杂性约束。在for_each的特定情况下(C ++标准中为25.2.4):

  

复杂性:恰好flast - first

所以在你的例子中它实际上是一个无操作。