问题描述
我有这段代码。此函数不会复制相邻的重复字符。它只保留其中一个。为了更简短,我决定将 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
。但是,递减开始迭代器是未定义的行为。
如果对 --container.begin() 求值,则开始迭代器不可递减且行为未定义
这意味着,您的第一个循环迭代已经是 UB。
请注意,有一个标准算法完全符合您的要求:std::unique
:
从范围 [first,last) 的每组连续等效元素中消除除第一个元素之外的所有元素,并返回范围的新逻辑结尾的结尾迭代器。
,把 C++ 中的迭代器想象成指针。如果您不仔细检查边界,它可能会指向不属于您的数据。它导致 std::out_of_range
异常