【发布时间】:2021-09-11 00:11:25
【问题描述】:
我在 Cppreference 上看到了算法 std::mismatch 的可能实现:
template<class InputIt1, class InputIt2>
std::pair<InputIt1, InputIt2>
mismatch(InputIt1 first1, InputIt1 last1, InputIt2 first2)
{
while (first1 != last1 && *first1 == *first2) {
++first1, ++first2;
}
return std::make_pair(first1, first2);
}
因此,如果第一个范围比第二个长,那么在某些时候,第二个范围中的越端迭代器将被取消引用,然后递增,从而产生未定义的行为。对?例如:
std::vector<int> v1{24, 10, 81, 7, 57};
std::vector<int> v2{24, 10, 81};
auto p = std::mismatch(v1.cbegin(), v1.cend(), v2.cbegin()); // UB?
-
所以元素是相等的,直到
v1位于7并且v2是past the last element所以它被取消引用然后递增,从而导致 UB。 -
我认为算法也必须在每次迭代时检查第二个范围是否在末尾:
first1 != last1 && first2 != last2 -
我认为第三和第四个版本是正确的:
template<class InputIt1, class InputIt2> std::pair<InputIt1, InputIt2> mismatch(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) { while (first1 != last1 && first2 != last2 && *first1 == *first2) { ++first1, ++first2; } return std::make_pair(first1, first2); } Fourth version template<class InputIt1, class InputIt2, class BinaryPredicate> std::pair<InputIt1, InputIt2> mismatch(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryPredicate p) { while (first1 != last1 && first2 != last2 && p(*first1, *first2)) { ++first1, ++first2; } return std::make_pair(first1, first2); } -
这里是cppreference主题的链接:
【问题讨论】:
-
如果您不确定范围的长度是否相同,那就是 wgat 接受两对开始/结束迭代器的重载。
-
@ItachiUchiwa 他们采用 4 个迭代器
[first1,last1)和[first2,last2)算法 5、6、7 和 8。还有 "...如果未提供 last2(重载 (1-4) ),它表示 first2 + (last1 - first1)...." 因此,在调用 1 到 4 中的任何一个之前,您必须确保合同为真。因此范围 2 必须至少与范围一样长1. -
@ItachiUchiwa 您应该使用 4 迭代器版本,除非您确定第一个范围不比第三个参数后面的范围长。如果您不确定,请始终使用 4 迭代器版本。
-
问题链接到的文档回答了问题。阅读返回值下的文字。
-
"我认为第三和第四个版本是对的:" -- 你说的“对”是什么意思?第三和第四个版本分别适用于实现重载 5 和 7,但不适用于实现其他重载。特别是对于重载 1,它们不可能正确,因为重载 1 需要三个参数,第三个版本需要四个参数,第四个版本需要五个参数。看起来你的“正确”概念会更好地针对声明而不是实现。