【问题标题】:How unsafe is it to use std::prev with string_iterator.begin()?将 std::prev 与 string_iterator.begin() 一起使用有多不安全?
【发布时间】:2021-08-11 08:19:12
【问题描述】:

我有这段代码。此功能不会复制相邻的重复字符。它只保留其中一个。为了更短,我决定将 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;
}

【问题讨论】:

  • 这是纯 UB。你不能在begin之前访问元素。

标签: c++ iterator undefined-behavior


【解决方案1】:

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

Bidirectional iterator:

开始迭代器不可递减,如果 --container.begin() 被评估,则行为未定义

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

请注意,有一个标准算法可以完全满足您的要求:std::unique:

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

【讨论】:

  • 确切地说我没有想到独特。我傻了哈哈
【解决方案2】:

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

【讨论】:

  • 我完全知道这意味着什么,但是使用这段代码,我从未遇到过未定义的行为或异常。这就是我问你们的原因。显然是独一无二的。问题解决了
  • 我从未遇到过未定义的行为。你认为你没有遇到它,但是你的代码确实有 UB。
  • 可能你是对的,但我希望你确定它是 UB。在 C 中,如果有 UB,那就更残酷了。
  • 我认为它之所以称为undefined behavior。这是不可预测的
猜你喜欢
  • 2011-12-04
  • 1970-01-01
  • 2022-10-20
  • 1970-01-01
  • 2014-02-28
  • 2013-11-01
  • 1970-01-01
  • 2022-10-21
  • 1970-01-01
相关资源
最近更新 更多