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

Posted

技术标签:

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

C++ STL 中的std::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】:

在SGI、MSDN 和GNU 文档中,stack 不提供迭代器。

【讨论】:

以上是关于std::stack 是不是公开迭代器?的主要内容,如果未能解决你的问题,请参考以下文章

迭代器

为啥 C++ 字符串迭代器不检查错误?

如何从 STL 类“继承”迭代器?

任何可迭代对象的值(而不是键)的通用迭代器

迭代器的注意事项

concurrent_vector 迭代器的算术:假设从迭代器中减去“begin ()”会给出索引是不是安全?