【问题标题】:Does std::stack expose iterators?std::stack 是否公开迭代器?
【发布时间】:2010-10-06 05:42:49
【问题描述】:

C++ STL 中的std::stack 是否公开了底层容器的任何迭代器,还是我应该直接使用该容器?

【问题讨论】:

    标签: c++ stl stack


    【解决方案1】:

    如果您需要带有迭代器的堆栈,您有两种选择:

    • std::vector 使用 push_back()pop_back()

    • std::dequepush_back()/pop_back()push_front()/pop_front()

    【讨论】:

      【解决方案2】:

      你在问

      std::stack 是否公开迭代器?

      很多人都给出了答案。如果我的英语更好,我可能也会理解“暴露”的确切含义。

      如果我们指的是 STL 和类 s​​td::stack 以及这里定义的预定义函数,答案是否定的。

      我的猜测是你在问,因为你想要迭代器。

      所以,如果我们更进一步,我们就有了函数 top()。并且 top() 可以解释为取消引用的迭代器。有了它,我们可以很容易地定义迭代器来堆叠元素。堆栈的内存保证是连续的。

      见下文。我们正在为 std::copy 定义和使用迭代器:

      #include <vector>
      #include <stack>
      #include <iostream>
      #include <algorithm>
      #include <iterator>
      #include <sstream>
      
      using Number = int;
      using UnderlyingContainer = std::vector<Number>;
      using Stack = std::stack< Number, UnderlyingContainer>;
      
      using StackIterator = const Number *;
      
      std::istringstream testData("5 8 1 4 9 3");
      
      int main()
      {
          // Put the test data onto the stack
          Stack stack{ UnderlyingContainer {std::istream_iterator<Number>(testData),std::istream_iterator<Number>()} };
      
          // Print the test data
          // Get iterators
          StackIterator end = &stack.top() + 1;
          StackIterator begin = end - stack.size();
      
          if (not stack.empty())
              std::copy(begin, end, std::ostream_iterator<Number>(std::cout, "\n"));
          return 0;
      }
      
      

      因此您可以为堆栈创建迭代器。但是,请注意:

      std::stack 有意将其元素隐藏在底层。因此,如果您对数据进行写访问,我会将其视为设计错误。通过 const 指针/迭代器进行读取访问对我来说是可以的。但也许你应该更好地使用 std::vector 。 . .

      【讨论】:

        【解决方案3】:

        std::stack 确实通过其受保护的接口将其底层容器(以及迭代器)暴露给子类std::stack 的底层容器对象对应于(受保护的)数据成员c。 所以如果你想访问它们,你可以扩展std::stack一点。

        template<typename T, typename Container = std::deque<T>>
        class iterable_stack
        : public std::stack<T, Container>
        {
            using std::stack<T, Container>::c;
        
        public:
        
            // expose just the iterators of the underlying container
            auto begin() { return std::begin(c); }
            auto end() { return std::end(c); }
        
            auto begin() const { return std::begin(c); }
            auto end() const { return std::end(c); }
        };
        
        int main()
        {
            iterable_stack<int> st;
        
            st.push(2);
            st.push(5);
            st.push(3);
            st.push(7);
            st.push(9);
        
            for(auto i: st)
                std::cout << i << ' ';
            std::cout << '\n';
        }
        

        输出:

        2 5 3 7 9 
        

        【讨论】:

        • 嗨,我正在尝试弄清楚如何使用 ::c ...但尚未成功。你能解释一下我们如何通过使用 ::c 在 Stack 上获得一个迭代器吗?我看到它“链接”到 container_type,但我现在的想法还不清楚。 ::c 的解释真的很有帮助!在此先感谢...
        【解决方案4】:

        根据堆栈的定义,堆栈没有迭代器。如果您需要带有迭代器的堆栈,则需要在其他容器(std::list、std::vector 等)之上自己实现它。 Stack doc is here.

        附:根据我从 Iraimbilanja 得到的评论,std::stack 默认使用 std::deque 来实现。

        【讨论】:

        • +1。另请注意,默认情况下 std::stack 使用 std::deque 作为其实现,因此这对于 iterstack 的默认实现也可能是一个不错的选择。另一个问题是,为什么你想要一个可迭代的堆栈,而不是一个直接的双端队列
        【解决方案5】:

        SGIMSDNGNU 文档中,stack 不提供迭代器。

        【讨论】:

          猜你喜欢
          • 2011-05-06
          • 1970-01-01
          • 1970-01-01
          • 2016-02-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-11
          • 2021-10-21
          相关资源
          最近更新 更多