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

如何在C++11/14中遍历std::vector的连续元素区间?

C++11/14下遍历std::vector连续元素区间的最优方案

核心问题:消除不必要的元素拷贝

原代码每次循环都会创建临时v_slice并拷贝元素,既浪费性能又冗余。核心优化方向是直接传递区间引用而非拷贝子vector,同时简化循环逻辑。

方案1:修改foo接受迭代器区间(推荐)

把foo改为接受迭代器范围,彻底避免元素拷贝,代码更简洁:

#include <vector>
#include <iostream>
#include <iterator>

template <typename Iter>
int foo(Iter begin, Iter end) {
    std::cout << "[";
    if (begin != end) {
        std::cout << *begin;
        ++begin;
        for (; begin != end; ++begin) {
            std::cout << "," << *begin;
        }
    }
    std::cout << "]" << std::endl;
    return 0;
}

int main() {
    std::vector<int> v = {0,1,2,3,4,5,6,7,8,9,10};
    std::vector<int> v_out;
    const int n = 3;

    // 简化循环条件:只要起始位置+n不超出vector末尾就继续
    for (auto begin = v.begin(); std::next(begin, n) <= v.end(); ++begin) {
        auto end = std::next(begin, n);
        v_out.push_back(foo(begin, end));
    }
}

方案2:自定义轻量级区间视图类(保留容器式接口)

如果希望foo的调用方式贴近原代码(比如支持范围for循环),可以写一个仅包装迭代器的轻量视图类,完全不拷贝元素:

#include <vector>
#include <iostream>
#include <iterator>

template <typename T>
class VectorView {
public:
    using iterator = typename std::vector<T>::const_iterator;

    VectorView(iterator begin, iterator end) : m_begin(begin), m_end(end) {}

    iterator begin() const { return m_begin; }
    iterator end() const { return m_end; }
    size_t size() const { return std::distance(m_begin, m_end); }
    const T& operator[](size_t idx) const { return *std::next(m_begin, idx); }

private:
    iterator m_begin;
    iterator m_end;
};

int foo(const VectorView<int>& v) {
    std::cout << "[";
    for(int e: v) {
        std::cout << e << ",";
    }
    std::cout << "]" << std::endl;
    return 0;
}

int main() {
    std::vector<int> v = {0,1,2,3,4,5,6,7,8,9,10};
    std::vector<int> v_out;
    const int n = 3;

    for (auto begin = v.begin(); std::next(begin, n) <= v.end(); ++begin) {
        VectorView<int> view(begin, std::next(begin, n));
        v_out.push_back(foo(view));
    }
}

方案3:适配std::for_each(STL算法风格)

生成所有区间的起始迭代器范围,用std::for_each遍历处理,符合STL编程习惯:

#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>

template <typename Iter>
int foo(Iter begin, Iter end) {
    std::cout << "[";
    if (begin != end) {
        std::cout << *begin;
        ++begin;
        for (; begin != end; ++begin) {
            std::cout << "," << *begin;
        }
    }
    std::cout << "]" << std::endl;
    return 0;
}

int main() {
    std::vector<int> v = {0,1,2,3,4,5,6,7,8,9,10};
    std::vector<int> v_out;
    const int n = 3;

    auto start_begin = v.begin();
    auto start_end = std::prev(v.end(), n - 1); // 最后一个合法起始位置

    std::for_each(start_begin, ++start_end, [&](auto begin) {
        auto end = std::next(begin, n);
        v_out.push_back(foo(begin, end));
    });
}

特殊情况:无法修改foo函数

如果必须保留foo(const std::vector<int>&)的接口,只能通过std::move减少临时对象的内存开销,但元素拷贝无法避免:

v_out.push_back(foo(std::vector<int>(begin, end)));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 04:01:03