过载运算符<<对于std :: stack

时间:2011-09-15 08:58:18

标签: c++ templates

代码优先:

//。cpp文件

template <typename T>
ostream &operator<<(ostream &os, stack<T> &st)
{
    while(! st.empty()) {
        os << st.top() << " ";
        st.pop();
    }
    return os;
}

template <typename T>
void stack_sorter(stack<T> &st)
{
    cout << st << endl;  //no output, st is empty?
    //...
}

int main()
{
    stack<int> s;
    s.push(4);
    s.push(3);
    s.push(5);
    cout << s << endl;  //ok
    stack_sorter(s);
}

输出:

5 3 4  //this was the output in main, not in stack_sorter
       //empty line, but s is not empty, why?

问题:

正如我在main中所做的那样,我将s传递给stack_soter(),但我在stack_sorter()中没有输出。 怎么了?

4 个答案:

答案 0 :(得分:5)

operator <<中,弹出所有值以输出它们。所以在cout << s << endl;之后,你的堆栈被清空了!

一种可能性是不通过引用传递,而是通过堆栈的副本。但是,这也将复制其中的所有对象。

答案 1 :(得分:3)

template <typename T>
ostream &operator<<(ostream &os, stack<T> st) //not &st
{
    while(! st.empty()) {
        os << st.top() << " ";
        st.pop();
}
return os;
}

答案 2 :(得分:2)

正如其他人所指出的,pop_back会使您的输出操作具有破坏性。在没有清空的情况下,根本无法读取堆栈的内容......这就是纯栈的本质。

此外,对标准类型的运算符进行重载是非常糟糕的做法。由于名称查找的工作方式(ADL,即语言找到要调用的重载函数的方式),因此重载函数应该与它们重载的类型位于相同的命名空间中。由于你不能将函数放在std::中,下一个最好的选择是全局命名空间,然后污染它。

但问题是可以解决的!幸运的是,stack提供了继承。派生类可以访问基础容器,并将其命名为c

template< typename value_arg, typename container_arg = std::deque< value_arg > >
struct printable_stack : std::stack< value_arg, container_arg > {

    // provide constructors :v( . This is better supported in C++11.
    printable_stack( container_arg const &in = container_arg() )
        : std::stack< value_arg, container_arg >( in ) {}

    friend std::ostream &operator<<
                            ( std::ostream &s, printable_stack const &o ) {
        for ( typename container_arg::iterator i = this->c.begin();
                                               i != this->c.end(); ++ i ) {
            s << * i << ' ';
        }
    }
};

此外,拥有一个专用类允许您提供一个额外的成员来保存分隔符字符串,因此它可以是一个简单的空格字符。

答案 3 :(得分:1)

st.pop()循环中对ostream &operator<<(ostream &os, stack<T> &st)的调用会清空堆栈。