如何让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(); } };
关键细节说明
- 继承与复用:通过继承std::stack,自动获得原类的所有成员函数(
push、pop、top、empty、size等),无需手动转发。 - 迭代器兼容性:迭代器的类型和行为完全依赖于底层容器——比如默认用std::deque时是随机访问迭代器,换成std::vector或std::list时,迭代器特性会自动适配。
- 标准合规性: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
相关产品推荐
相关产品推荐

