[英]overload operator<< for std::stack
代碼優先:
//.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()中沒有輸出。 怎么了?
在operator <<
,彈出所有值以輸出它們。 所以在cout << s << endl;
,您的堆棧已清空!
一種可能是不通過引用傳遞,而是堆棧的副本。 但是,這還將復制其中的所有對象。
template <typename T>
ostream &operator<<(ostream &os, stack<T> st) //not &st
{
while(! st.empty()) {
os << st.top() << " ";
st.pop();
}
return os;
}
正如其他人指出的那樣, 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 << ' ';
}
}
};
此外,擁有專用的類可以使您提供一個額外的成員來容納分隔符字符串,因此它可以是除簡單的空格字符之外的其他內容。
您在ostream &operator<<(ostream &os, stack<T> &st)
循環中對st.pop()
調用將清空堆棧。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.