You need to enable JavaScript to run this app. 对string的begin()迭代器使用std::prev有多不安全?附去重代码优化咨询
优惠活动
大模型
产品
解决方案
定价
更多

对string的begin()迭代器使用std::prev有多不安全?附去重代码优化咨询

代码存在的问题

  • 存在明确的未定义行为:你写的循环首次迭代时it就是str.cbegin(),C标准明确规定,对前向迭代器的起始位置调用std::prev属于未定义行为,和C语言中访问数组首地址之前的内存风险完全一致,不存在“C规则更宽松”的说法。你当前代码能正常运行只是编译器未开启迭代器边界检查的巧合,换编译环境、开优化都可能直接崩溃。
  • 逻辑本身存在缺陷:就算忽略未定义行为,你也没有把字符串的第一个字符加入结果集,比如输入"ab"的运行结果会是"b",直接丢失了首字符,完全不符合需求。

更优的实现方案

两种可选方案均为O(n)时间复杂度,正确性有保障:

方案1:直接使用STL内置的std::unique

这是最简洁、经过标准库充分优化的实现,专门用于去除相邻重复元素:

#include <algorithm>
#include <string>

std::string suppDouble(const std::string& str)
{
    if (str.size() <= 1) return str;
    std::string res = str;
    auto dup_end = std::unique(res.begin(), res.end());
    res.erase(dup_end, res.end());
    return res;
}

如果不需要保留原字符串,你还可以直接传值而非传常量引用,省去一次拷贝开销。

方案2:手写实现(适合需要自定义去重规则的场景)

提前预分配内存避免动态扩容,同时规避迭代器边界问题:

#include <string>

std::string suppDouble(const std::string& str)
{
    if (str.empty()) return {};
    std::string token;
    token.reserve(str.size()); // 提前分配足够空间,消除后续push_back的扩容开销
    token.push_back(str.front());
    for (auto it = str.cbegin() + 1; it != str.cend(); ++it) {
        if (*it != token.back()) {
            token.push_back(*it);
        }
    }
    return token;
}

内容的提问来源于stack exchange,提问作者Etienne Armangau

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.19 12:27:09