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

如何扩展std::array实现循环覆盖的固定大小数组?

复用std::array实现循环覆盖数组的简便方案

你不需要从头实现完整的类,直接复用std::array的所有功能,只添加循环覆盖的核心逻辑即可,下面是两种可行方案:

方案一:继承std::array(最简便)

通过继承std::array<T, N>,自动获得它的所有成员函数(比如size()、fill()、swap()等),仅重写下标运算符和添加push方法,再实现自定义迭代器支持逻辑顺序的遍历:

#include <array>
#include <iterator>

template <typename T, std::size_t N>
class CircularArray : public std::array<T, N> {
private:
    std::size_t head = 0;
public:
    // 继承std::array的所有构造函数,支持各种初始化方式
    using std::array<T, N>::array;

    // 重写下标运算符,实现循环逻辑访问
    T& operator[](std::size_t i) {
        std::size_t pos = (head + i) % N;
        return std::array<T, N>::operator[](pos);
    }

    const T& operator[](std::size_t i) const {
        std::size_t pos = (head + i) % N;
        return std::array<T, N>::operator[](pos);
    }

    // 循环覆盖的push方法,支持左值和右值引用
    void push(const T& val) {
        std::array<T, N>::operator[](head) = val;
        head = (head + 1) % N;
    }

    void push(T&& val) {
        std::array<T, N>::operator[](head) = std::move(val);
        head = (head + 1) % N;
    }

    // 自定义迭代器,支持范围for循环和标准库算法(按逻辑顺序遍历)
    class iterator {
    private:
        typename std::array<T, N>::iterator base_it;
        typename std::array<T, N>::iterator start_it;
        std::size_t remaining;
    public:
        using value_type = T;
        using reference = T&;
        using pointer = T*;
        using difference_type = std::ptrdiff_t;
        using iterator_category = std::forward_iterator_tag;

        iterator(typename std::array<T, N>::iterator it, typename std::array<T, N>::iterator start, std::size_t rem)
            : base_it(it), start_it(start), remaining(rem) {}

        reference operator*() const { return *base_it; }
        pointer operator->() const { return base_it.operator->(); }

        iterator& operator++() {
            if (remaining == 0) return *this;
            ++base_it;
            if (base_it == std::array<T, N>::end()) {
                base_it = std::array<T, N>::begin();
            }
            --remaining;
            return *this;
        }

        iterator operator++(int) {
            auto temp = *this;
            ++(*this);
            return temp;
        }

        bool operator==(const iterator& other) const {
            return remaining == other.remaining && base_it == other.base_it;
        }

        bool operator!=(const iterator& other) const {
            return !(*this == other);
        }
    };

    iterator begin() {
        return iterator(std::array<T, N>::begin() + head, std::array<T, N>::begin(), N);
    }

    iterator end() {
        return iterator(std::array<T, N>::begin() + head, std::array<T, N>::begin(), 0);
    }

    // const版本迭代器
    class const_iterator {
    private:
        typename std::array<T, N>::const_iterator base_it;
        typename std::array<T, N>::const_iterator start_it;
        std::size_t remaining;
    public:
        using value_type = T;
        using reference = const T&;
        using pointer = const T*;
        using difference_type = std::ptrdiff_t;
        using iterator_category = std::forward_iterator_tag;

        const_iterator(typename std::array<T, N>::const_iterator it, typename std::array<T, N>::const_iterator start, std::size_t rem)
            : base_it(it), start_it(start), remaining(rem) {}

        reference operator*() const { return *base_it; }
        pointer operator->() const { return base_it.operator->(); }

        const_iterator& operator++() {
            if (remaining == 0) return *this;
            ++base_it;
            if (base_it == std::array<T, N>::cend()) {
                base_it = std::array<T, N>::cbegin();
            }
            --remaining;
            return *this;
        }

        const_iterator operator++(int) {
            auto temp = *this;
            ++(*this);
            return temp;
        }

        bool operator==(const const_iterator& other) const {
            return remaining == other.remaining && base_it == other.base_it;
        }

        bool operator!=(const const_iterator& other) const {
            return !(*this == other);
        }
    };

    const_iterator begin() const {
        return const_iterator(std::array<T, N>::cbegin() + head, std::array<T, N>::cbegin(), N);
    }

    const_iterator end() const {
        return const_iterator(std::array<T, N>::cbegin() + head, std::array<T, N>::cbegin(), 0);
    }

    const_iterator cbegin() const { return begin(); }
    const_iterator cend() const { return end(); }
};

方案优势

  • 零成本获得std::array的所有功能,无需重复实现size()、fill()等方法
  • 支持std::array的所有初始化方式(聚合初始化、列表初始化等)
  • 自定义迭代器保证范围for循环和标准库算法按逻辑顺序遍历(从head开始,循环绕回数组开头)

方案二:组合std::array(更安全)

如果担心继承聚合类的潜在问题(虽然std::array无虚函数,切片风险极低),可以将std::array作为成员变量,手动导入其成员函数:

#include <array>
#include <iterator>
#include <utility>

template <typename T, std::size_t N>
class CircularArray {
private:
    std::array<T, N> arr;
    std::size_t head = 0;
public:
    // 导入std::array的类型定义
    using value_type = typename std::array<T, N>::value_type;
    using reference = typename std::array<T, N>::reference;
    using const_reference = typename std::array<T, N>::const_reference;
    using pointer = typename std::array<T, N>::pointer;
    using const_pointer = typename std::array<T, N>::const_pointer;
    using size_type = typename std::array<T, N>::size_type;
    using difference_type = typename std::array<T, N>::difference_type;

    // 构造函数
    CircularArray() = default;
    CircularArray(const std::array<T, N>& other) : arr(other) {}
    CircularArray(std::array<T, N>&& other) : arr(std::move(other)) {}
    template <typename... Args>
    explicit CircularArray(Args&&... args) : arr(std::forward<Args>(args)...) {}

    // 导入std::array的核心成员函数
    bool empty() const noexcept { return arr.empty(); }
    size_type size() const noexcept { return arr.size(); }
    size_type max_size() const noexcept { return arr.max_size(); }
    void fill(const T& val) { arr.fill(val); }
    void swap(CircularArray& other) noexcept(std::is_nothrow_swappable_v<T>) {
        arr.swap(other.arr);
        std::swap(head, other.head);
    }

    // 自定义循环访问和push
    T& operator[](std::size_t i) {
        std::size_t pos = (head + i) % N;
        return arr[pos];
    }

    const T& operator[](std::size_t i) const {
        std::size_t pos = (head + i) % N;
        return arr[pos];
    }

    void push(const T& val) {
        arr[head] = val;
        head = (head + 1) % N;
    }

    void push(T&& val) {
        arr[head] = std::move(val);
        head = (head + 1) % N;
    }

    // 同样添加自定义迭代器(代码同方案一,只需将std::array<T, N>::替换为arr.即可)
    class iterator {
    private:
        typename std::array<T, N>::iterator base_it;
        typename std::array<T, N>::iterator start_it;
        std::size_t remaining;
    public:
        using value_type = T;
        using reference = T&;
        using pointer = T*;
        using difference_type = std::ptrdiff_t;
        using iterator_category = std::forward_iterator_tag;

        iterator(typename std::array<T, N>::iterator it, typename std::array<T, N>::iterator start, std::size_t rem)
            : base_it(it), start_it(start), remaining(rem) {}

        reference operator*() const { return *base_it; }
        pointer operator->() const { return base_it.operator->(); }

        iterator& operator++() {
            if (remaining == 0) return *this;
            ++base_it;
            if (base_it == arr.end()) {
                base_it = arr.begin();
            }
            --remaining;
            return *this;
        }

        iterator operator++(int) {
            auto temp = *this;
            ++(*this);
            return temp;
        }

        bool operator==(const iterator& other) const {
            return remaining == other.remaining && base_it == other.base_it;
        }

        bool operator!=(const iterator& other) const {
            return !(*this == other);
        }
    };

    iterator begin() {
        return iterator(arr.begin() + head, arr.begin(), N);
    }

    iterator end() {
        return iterator(arr.begin() + head, arr.begin(), 0);
    }

    // const迭代器同理,此处省略
};

方案优势

  • 完全避免继承可能带来的意外问题,代码更健壮
  • 对std::array的依赖更清晰,易于维护

注意事项

  • 如果不需要按逻辑顺序遍历,仅保留std::array的原始迭代器,可以省略自定义迭代器的实现,直接使用arr.begin()/arr.end()(继承方案则用std::array<T, N>::begin())
  • 两种方案都支持C++17及以上的范围for循环,以及std::sort、std::for_each等标准库算法

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:49:51