基于http://en.cppreference.com/w/cpp/algorithm/equal的std::equal
的实施如下:
template<class InputIt1, class InputIt2>
bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
{
for (; first1 != last1; ++first1, ++first2) {
if (!(*first1 == *first2)) {
return false;
}
}
return true;
}
当我将string str1 = "abcd"
与string str2 = "abc"
进行比较时,equal(str1.begin(), str1.end(), str2.begin())
会按预期返回false
。由于abcd
只有一个字符,我想知道上述实现是否将'd'
与*str2.end()
进行了比较。看起来是这样,但不是不安全吗? str2.end()
可能指向任何内容,可能是'd'
。
答案 0 :(得分:4)
假设您正在谈论std::string
或std::wstring
,并假设您正在讨论不包含嵌入空值的字符串(如示例中的文字)。然后:
由于C ++ 11解除引用end()
实际上保证为非const
实例产生null-char值。所以比较在那里停止,因为它与此时的另一个字符串的值不同,或者它是最后一个迭代器位置。
std::basic_string::operator[]
“ 返回:
*(begin() + pos)
ifpos < size()
,否则引用T
类型的对象,其值为{{1} }};参考值不得修改。
对于语言律师来说,这里有一个很好的点,即charT()
定义了空值效应,operator[]
是根据end
以外的迭代器定义的,因此end
迭代器原则上可以是特殊的。
但这显然违背了尽可能提供C字符串语义的意图。
答案 1 :(得分:2)
在这种情况下,您将五元素数组与四元素数组进行比较(C风格和C ++风格的字符串都具有终止NUL字符),第四个元素不同。
如果您改为
char str1[4] = { 'a', 'b', 'c', 'd' };
和
char str2[3] = { 'a', 'b', 'c' };
然后你的调用将执行超出边界的读取(未定义的行为)。
答案 2 :(得分:1)
是的,确实如此。这就是为什么在C ++ 14中,委员会添加了equal
(以及mismatch
和is_permutation
)的“四个迭代器”版本。
equal(s1.begin(), s1.end(), s2.begin(), s2.end())
不会取消引用s2.end()
(并且如果范围大小不同,可以快速返回false,以启动!)