假设我有这样的代码:
void printHex(std::ostream& x){
x<<std::hex<<123;
}
..
int main(){
std::cout<<100; // prints 100 base 10
printHex(std::cout); //prints 123 in hex
std::cout<<73; //problem! prints 73 in hex..
}
我的问题是,在从函数返回后,是否有任何方法可以将cout的状态“恢复”到原来的状态? (有点像std :: boolalpha和std :: noboolalpha ..)?
谢谢 .
6 回答
你需要
#include <iostream>
或#include <ios>
然后在需要时:您可以将这些放在函数的开头和结尾,或者查看this answer,了解如何在RAII中使用它 .
Boost IO Stream State Saver似乎正是您所需要的 . :-)
基于代码段的示例:
请注意,此处提供的答案不会恢复
std::cout
的完整状态 . 例如,即使在调用.flags()
之后,std::setfill
也将"stick" . 更好的解决方案是使用.copyfmt
:将打印:
而不是:
我使用此答案中的示例代码创建了一个RAII类 . 如果你有一个在iostream上设置标志的函数有多个返回路径,那么这个技术的最大优势就来了 . 无论使用哪个返回路径,都将始终调用析构函数,并始终重置标志 . 函数返回时,没有机会忘记恢复标志 .
然后,只要您想保存当前标志状态,就可以通过创建IosFlagSaver的本地实例来使用它 . 当此实例超出范围时,将恢复标志状态 .
通过一些修改使输出更具可读性:
您可以在stdout缓冲区周围创建另一个包装器:
在一个功能:
当然,如果性能是一个问题,这有点贵,因为它正在复制整个
ios
对象(但不是缓冲区),包括你付出但不太可能使用的一些东西,比如locale .否则我觉得如果你要使用
.flags()
,最好是保持一致并使用.setf()
而不是<<
语法(纯粹的风格问题) .正如其他人所说的那样,为方便起见,你可以把上面的内容(和
.precision()
和.fill()
,但通常不是那些通常不会被修改并且更重的单词相关的东西)放在一个类中,并使其异常安全;构造函数应该接受std::ios&
.