将 std::prev 与 string_iterator.begin() 一起使用有多不安全?

问题描述

我有这段代码。此函数不会复制相邻的重复字符。它只保留其中一个。为了更简短,我决定将 std::prev 与 iterator.begin() 一起使用。我知道这是一种(非常)糟糕的做法,我来自 C,但在 C++ 中有些不同。未定义的行为几乎不存在。告诉我伙计们。我可以很容易地改变我的方法。如果你有更快的方法,我也很感兴趣。

string suppDouble(const string& str)
{
    if (str.size() <= 1) return str;

    string token;
    for (auto it = str.cbegin(); it != str.cend(); it++)
    {
        if (*(std::prev(it)) != *it) token.push_back(*it);
    }
    return token;
}

解决方法

std::prev 在您的情况下有效地执行 it - 1。但是,递减开始迭代器是未定义的行为。

Bidirectional iterator

如果对 --container.begin() 求值,则开始迭代器不可递减且行为未定义

这意味着,您的第一个循环迭代已经是 UB。

请注意,有一个标准算法完全符合您的要求:std::unique:

从范围 [first,last) 的每组连续等效元素中消除除第一个元素之外的所有元素,并返回范围的新逻辑结尾的结尾迭代器。

,

把 C++ 中的迭代器想象成指针。如果您不仔细检查边界,它可能会指向不属于您的数据。它导致 std::out_of_range 异常