使用 std::prev 和 string_iterator.begin() 有多不安全?
How unsafe is it to use std::prev with string_iterator.begin()?
我有这段代码。此函数不复制相邻的副本 chars.It 只保留其中一个。为了缩短时间,我决定使用 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;
}
将 C++ 中的迭代器想象成指针。如果您不仔细检查边界,它可能指向不属于您的数据。它导致 std::out_of_range
异常
std::prev
在您的情况下有效 it - 1
。但是,递减开始迭代器是未定义的行为。
The begin iterator is not decrementable and the behavior is undefined if --container.begin() is evaluated
这意味着,您的第一个循环迭代已经是 UB。
请注意,有一个标准算法可以完全满足您的需求:std::unique
:
Eliminates all except the first element from every consecutive group of equivalent elements from the range [first, last) and returns a past-the-end iterator for the new logical end of the range.
我有这段代码。此函数不复制相邻的副本 chars.It 只保留其中一个。为了缩短时间,我决定使用 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;
}
将 C++ 中的迭代器想象成指针。如果您不仔细检查边界,它可能指向不属于您的数据。它导致 std::out_of_range
异常
std::prev
在您的情况下有效 it - 1
。但是,递减开始迭代器是未定义的行为。
The begin iterator is not decrementable and the behavior is undefined if --container.begin() is evaluated
这意味着,您的第一个循环迭代已经是 UB。
请注意,有一个标准算法可以完全满足您的需求:std::unique
:
Eliminates all except the first element from every consecutive group of equivalent elements from the range [first, last) and returns a past-the-end iterator for the new logical end of the range.