C ++ steam对象具有状态。如果一个人写一段代码,如
using namespace std;
cout << hex << setw(8) << setfill('0') << x << endl;
忘记设置流状态。这将导致其他一些不相关的代码出现问题。做起来很繁琐&#34;设置&#34;并且&#34;退回&#34;配对。除此之外,在我看来,它也反对RAII背后的惯例。
我的问题是:是否有可能只用一层薄薄的包裹来使这些状态操作成为类RAII。也就是说,在分号表达式结束后,流状态会自动设置回默认值。
更新:按照@ 0x499602D2提供的链接,一个解决方法可能类似
#include <boost/io/ios_state.hpp>
#include <ios>
#include <iostream>
#include <ostream>
#define AUTO_COUT(x) {\
boost::io::ios_all_saver ias( cout );\
x;\
}while(0)
然后可以使用像
这样的宏AUTO_COUT(cout << hex << setw(8) << setfill('0') << x << endl);
顺便说一下,如果在多线程程序中出现有趣的事情,可以将一个锁定字段添加到boost :: io :: ios_state的保护类中,这可能是一个好主意。或者他们已经这样做了?
答案 0 :(得分:3)
我将建议另一种方法。操纵符适用于std::[i|o]stream
实例,但它们对由std::[i|o]streambuf
管理的std::[i|o]stream
无效。
因此,您可以创建自己的std::[i|o]stream
,它将具有自己的格式化状态,但写入相同的缓冲区std::cout
会使用:
#include <iostream>
#include <iomanip>
int main()
{
std::cout << std::hex << 32 << "\n";
std::ostream os(std::cout.rdbuf());
os << 32 << "\n" << std::hex;
std::cout << std::dec;
os << 32 << "\n";
std::cout << 32 << "\n";
}
输出:
20
32
20
32
这仅使用标准库中的功能,并且由于未触及原始流,因此应用操纵器非常简单(因为每个线程在不同的流上运行)。现在,实际写入和读取的线程安全性取决于托管流缓冲区的线程安全性。
答案 1 :(得分:2)
我曾经写过一个实用课程供我个人使用。 (我不知道它是否像升级代码一样完美,但它对我有用 - 所以,我敢于分享。)
#include <iostream>
#include <iomanip>
/** provides a helper class to work with streams.
*
* It stores current format states of a stream in constructor and
* recovers these settings in destructor.
*
* Example:
* <pre>
* { // backup states of std::cout
* IOSFmtBackup stateCOut(std::cout);
* // do some formatted output
* std::cout
* << "dec: " << std::dec << 123 << std::endl
* << "hex: " << std::hex << std::setw(8) << std::setfill('0')
* << 0xdeadbeef << std::endl;
* } // destruction of stateCOut recovers former states of std::cout
* </pre>
*/
class IOSFmtBackup {
// variables:
private:
/// the concerning stream
std::ios &_stream;
/// the backup of formatter states
std::ios _fmt;
// methods:
public:
/// @name Construction & Destruction
//@{
/** constructor.
*
* @param stream the stream for backup
*/
explicit IOSFmtBackup(std::ios &stream):
_stream(stream), _fmt(0)
{
_fmt.copyfmt(_stream);
}
/// destructor.
~IOSFmtBackup() { _stream.copyfmt(_fmt); }
// disabled:
IOSFmtBackup(const IOSFmtBackup&) = delete;
IOSFmtBackup& operator=(const IOSFmtBackup&) = delete;
//@}
};
int main()
{
{ // backup states of std::cout
IOSFmtBackup stateCOut(std::cout);
// do some formatted output
std::cout
<< "dec: " << std::dec << 123 << std::endl
<< "hex: " << std::hex << std::setw(8) << std::setfill('0')
<< 0xdeadbeef << std::endl
<< "123 in current: " << 123 << std::endl;
} // destruction of stateCOut recovers former states of std::cout
// check whether formatting is recovered
std::cout << "123 after recovered: " << 123 << std::endl;
return 0;
}
在ideone (life demo)上进行了编译和测试。
输出:
dec: 123
hex: deadbeef
123 in current: 7b
123 after recovered: 123