You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

按指定字符串列表遍历vector写入文件:哪种实现开销更低?

哪种实现方法的整体开销更低?

需要将一个临时std::vector<std::string>的元素,按照给定std::vector<std::string> extensions的顺序写入文件。给定代码如下:

std::vector<std::string> data {
    "jpg  yuvj420p 1080x2400 1:1   9:20",
    "jpeg yuvj420p 1536x2048 72:72 3:4",
    "jpg  yuvj444p 1920x1080 1:1   16:9",
    "png  rgba     150x150   NA    NA",
    // ... 最多还有35(或56?)个元素,均以extensions中的某字符串开头
};
std::vector<std::string> extensions {
    "png", "jpg", "jpeg", // ... 还有2到4个扩展
};
std::ofstream file ("data.txt");

现有两种实现方法:

1. 直接遍历法

for (auto& ext : extensions)
{
    for (auto& it : data)
        if (it.starts_with(ext))
            file << it << '\n';
}

2. 使用std::erase_if法

for (auto& ext : extensions)
{
    std::erase_if(
        data,
        [&ext](std::string& it) {
            if (it.starts_with(ext)) {
                file << it << '\n';
                return true;
            } else return false;
        }
    );
}

两种方法均可得到符合extensions顺序的文件内容。第二种方法试图避免后续外层循环中重复遍历已写入文件的data元素,但std::erase_if会带来额外开销:包括(data.size() - 已匹配元素数)次谓词调用、元素移动操作,以及extensions.size()次data.erase调用。请问哪种方法的整体开销更低?


结论:直接遍历法开销更低(针对当前场景)

具体分析:

  • 直接遍历法的开销:
    本质是extensions.size() × data.size()次starts_with调用,没有内存元素移动、删除等操作。虽然会重复遍历已写入的元素,但结合题目里的规模——data最多56个元素,extensions最多6个左右,总调用次数最多56×6=336次,这个量级的字符串前缀判断开销微乎其微,完全可以忽略。

  • std::erase_if法的额外成本:
    每次erase_if确实会减少后续遍历的元素数量,但代价是:

    1. 每次匹配到元素后,需要将vector中后续的所有元素向前移动(即使是string的移动语义,也涉及指针、长度等成员的赋值,而非零成本);
    2. erase操作本身需要调整vector的内部状态;
    3. 逻辑上比直接遍历更复杂,维护成本更高。

    对于只有几十元素的data,这些额外开销的总和,远大于直接遍历多做的几次starts_with判断。

补充:

如果data的规模达到上万甚至更大,erase_if法减少遍历次数的收益才会超过元素移动的开销,但当前场景完全不需要考虑这种情况。直接遍历法不仅开销更低,代码也更直观易懂。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 08:52:31