代码优先:
//。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()中没有输出。 怎么了?
答案 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)
的调用会清空堆栈。