在“abcd”和“abc”的情况下,“std::equal”是否取消引用“end()”

Does `std::equal` dereference the `end()` in the case `abcd` and `abc`?

本文关键字:是否 equal 取消 end 引用 abcd abc 情况下 std      更新时间:2023-10-16
基于

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长了一个字符,我想知道上面的实现是否与*str2.end()相比'd'。看起来是这样,但这不是不安全吗? str2.end()可能指向任何东西,也可能是'd'

假设您正在谈论std::stringstd::wstring,并且假设您正在谈论不包含嵌入空值的字符串(如示例中的文本(。然后:

由于 C++11 取消引用end()实际上保证也为非const实例生成空字符值。因此,比较到此为止,因为此时它与另一个字符串的值不同,或者它是最后一个迭代器位置。

C++11 §21.4.5/2
关于std::basic_string::operator[]

">返回*(begin() + pos)如果pos < size(),否则引用值为 charT()T 类型的对象的引用;引用的值不得修改。

对于语言律师来说,这里有一个很好的点,即空值效应是为operator[]定义的,它是根据end以外的迭代器定义的,因此end迭代器原则上可以是特例。

但这显然与尽可能提供 C 字符串语义的意图背道而驰。

在本例中,您将五元素数组与四元素数组进行比较(C 样式和 C++ 样式字符串都具有终止 NUL 字符(,并且第四个元素不同。

如果你有

char str1[4] = { 'a', 'b', 'c', 'd' };

char str2[3] = { 'a', 'b', 'c' };

然后,您的调用将执行超出边界的读取(未定义的行为(。

是的,确实如此。 这就是为什么在第 14 C++,委员会添加了 equal 的"四迭代器"版本(以及 mismatchis_permutation (。

equal(s1.begin(), s1.end(), s2.begin(), s2.end())

不会取消引用s2.end()(如果范围大小不同,可以快速返回 false,以启动!