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

如何让C++ STACK容器可迭代?能否基于std::stack实现带迭代器的myStack类?

实现带迭代器特性的std::stack扩展类

std::stack本质是容器适配器,默认基于std::deque实现,本身不提供迭代器接口——因为它的设计目标是模拟栈的"后进先出"行为,屏蔽随机访问能力。要扩展出迭代器特性,核心思路是暴露其底层容器的迭代器,同时保留原std::stack的所有成员函数。

实现方案

直接继承std::stack,利用其受保护的底层容器成员c(C++标准明确规定std::stack必须包含这个受保护成员)来提供迭代器接口,同时复用原类的所有构造函数和成员函数:

#include <stack>
#include <deque>
#include <iterator>

template <typename T, typename Container = std::deque<T>>
class myStack : public std::stack<T, Container> {
public:
    // 复用基类的所有构造函数
    using std::stack<T, Container>::stack;

    // 定义迭代器类型,与底层容器保持一致
    using iterator = typename Container::iterator;
    using const_iterator = typename Container::const_iterator;
    using reverse_iterator = typename Container::reverse_iterator;
    using const_reverse_iterator = typename Container::const_reverse_iterator;

    // 实现迭代器访问接口
    iterator begin() noexcept { return this->c.begin(); }
    const_iterator begin() const noexcept { return this->c.begin(); }
    const_iterator cbegin() const noexcept { return this->c.cbegin(); }

    iterator end() noexcept { return this->c.end(); }
    const_iterator end() const noexcept { return this->c.end(); }
    const_iterator cend() const noexcept { return this->c.cend(); }

    reverse_iterator rbegin() noexcept { return this->c.rbegin(); }
    const_reverse_iterator rbegin() const noexcept { return this->c.rbegin(); }
    const_reverse_iterator crbegin() const noexcept { return this->c.crbegin(); }

    reverse_iterator rend() noexcept { return this->c.rend(); }
    const_reverse_iterator rend() const noexcept { return this->c.rend(); }
    const_reverse_iterator crend() const noexcept { return this->c.crend(); }
};

关键细节说明

  1. 继承与复用:通过继承std::stack,自动获得原类的所有成员函数(push、pop、top、empty、size等),无需手动转发。
  2. 迭代器兼容性:迭代器的类型和行为完全依赖于底层容器——比如默认用std::deque时是随机访问迭代器,换成std::vector或std::list时,迭代器特性会自动适配。
  3. 标准合规性:C++标准规定std::stack的底层容器必须通过受保护成员c暴露,因此该实现具有良好的跨编译器兼容性(主流GCC、Clang、MSVC均支持)。

使用示例

#include <iostream>

int main() {
    myStack<int> s;
    s.push(1);
    s.push(2);
    s.push(3);

    // 范围for循环遍历
    for (int num : s) {
        std::cout << num << " ";
    }
    std::cout << "\n";

    // 反向迭代器遍历
    for (auto it = s.rbegin(); it != s.rend(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    // 原std::stack的成员函数正常使用
    std::cout << "栈顶元素: " << s.top() << "\n";
    s.pop();
    std::cout << "弹出后栈大小: " << s.size() << "\n";

    return 0;
}

输出结果:

1 2 3 
3 2 1 
栈顶元素: 3
弹出后栈大小: 2

替代方案(无继承)

如果担心依赖std::stack的底层实现细节,也可以采用组合模式:在myStack中封装一个std::stack成员,手动转发所有原成员函数,再添加迭代器接口。这种方式代码量更大,但完全不依赖基类的内部细节:

template <typename T, typename Container = std::deque<T>>
class myStack {
private:
    std::stack<T, Container> stack_;
public:
    // 转发构造函数
    myStack() = default;
    template <typename InputIt>
    myStack(InputIt first, InputIt last) : stack_(first, last) {}
    explicit myStack(const Container& cont) : stack_(cont) {}
    explicit myStack(Container&& cont) noexcept : stack_(std::move(cont)) {}

    // 转发原stack的成员函数
    bool empty() const noexcept { return stack_.empty(); }
    size_t size() const noexcept { return stack_.size(); }
    T& top() { return stack_.top(); }
    const T& top() const { return stack_.top(); }
    void push(const T& value) { stack_.push(value); }
    void push(T&& value) { stack_.push(std::move(value)); }
    template <typename... Args>
    decltype(auto) emplace(Args&&... args) { return stack_.emplace(std::forward<Args>(args)...); }
    void pop() { stack_.pop(); }
    void swap(myStack& other) noexcept { stack_.swap(other.stack_); }

    // 注意:组合模式下无法直接访问std::stack的受保护成员c,
    // 若要实现迭代器,需自行封装底层容器而非依赖std::stack,代码量会大幅增加
};

显然,组合模式的缺点是需要手动转发所有成员函数,代码冗余,因此继承方式是更高效的选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 19:30:34