我的程序会将大量短行打印到cout
。
作为一个有点人为的例子,我的线条看起来有点像这样:
cout<<"The variable's value is: "<<variable<<endl;
我希望程序运行 fast 并且我确实认为endl
正在杀死我,因为它每次使用时都会在cout
上启动缓冲区刷新。
现在,互联网上的一些人说我可以这样做:
cout<<"The variable's value is: "<<variable<<"\n";
但这似乎不是一个好的解决方案,因为endl
抽象出特定于系统的特定方式可以指定一个结束行,而\n
则没有。这似乎也是一个糟糕的解决方案,因为如果我将来需要缓冲,那么我将不得不修改整个代码库。
因此,我问,有没有办法禁用endl
的缓冲区刷新方面?
修改
进一步挖掘似乎表明endl
和\n
都尊重操作系统可能选择结束它的各种方式。 It also seems输出流检测到它是否处于潜在的交互状态并相应地缓冲和刷新。因此:问题可以通过手动告诉输出流执行积极缓冲来解决......如果我能弄清楚如何做到这一点。
答案 0 :(得分:8)
endl抽象特定系统特定的方式可以指定结束行,其中\ n不是“。
std::endl
定义为输出'\n'
后跟同花。正确抽象系统特定的换行符只是'\n'
。
为防止刷新,我们不会使用std::endl
。此外,如果标准输出是或可能连接到交互设备,则标准输出可以是行缓冲的,在这种情况下,换行符将刷新流。如果这是一个问题,请使用连接到指定文件的ofstream
。我认为在类Unix系统上,线路缓冲仅在标准输出是终端时发生。
答案 1 :(得分:5)
endl
冲洗。如果您不想要这种行为,请不要使用endl
。如果您想轻松更改代码,请使用自己的操作符:
inline std::ostream& myendl( std::ostream& os ){
os.put(os.widen('\n'));
return os;
}
通过这种方式,您可以轻松地在一个位置更改myendl
的行为。
答案 2 :(得分:3)
根据http://en.cppreference.com/w/cpp/io/manip/endl
endl ::将一个endline字符插入到输出序列os中并将其刷新,就像调用os.put(os.widen('\n'))
后跟os.flush()
一样。
所以看起来你只想写os.put(os.widen('\n'))
,从这个定义来看,它应该是安全,可移植和正确的,并且满足你的主要需求。
答案 3 :(得分:1)
有std :: nounitbuf记录在这个问题上有一些影响。 但是,我没有发现任何差异。为了绕过所有ostream关于何时或何时不冲洗的想法,我尝试了这个:
std::ostringstream oss;
// std::cout << std::nounitbuf;
for( int i = 0; i < 1000000; i++ ){
// std::cout << "Test " << "file" << '\n';
oss << "Test " << "file" << '\n';
}
std::cout << oss.str();
这将执行时间从约33秒提高到约25秒。
如果您的输出转到xterm,您的执行速度会受到xterm的滚动等工作的严格限制。如果您使用管道过滤掉不必要的行,您会看到速度急剧增加,例如
./program | grep -v "The variable"
答案 4 :(得分:1)
如果刷新是问题,您可以实现一个流缓冲区,它覆盖sync()
成员函数,只有在您指定的情况下才刷新到外部设备。如果您打算在整个计划中更改这些首选项,它还有义务创建您自己的操纵器flush_on_endl
和noflush_on_endl
。
#include <iostream>
static int disable() {
static int index(std::ios_base::xalloc());
return index;
}
class save_buffer
{
public:
save_buffer(std::ios& other)
: str(other), buf(other.rdbuf())
{ }
~save_buffer() { str.rdbuf(buf); }
private:
std::ios& str;
std::streambuf* buf;
};
class syncing_buffer_optional : public std::streambuf, private save_buffer
{
public:
syncing_buffer_optional(std::ostream& other)
: save_buffer(other),
buf(other.rdbuf()),
disable_sync(other.iword(disable()))
{ }
std::streambuf::int_type overflow(std::streambuf::int_type c)
{
buf->sputc(c);
return 0;
}
int sync()
{
return disable_sync? 0: buf->pubsync();
}
private:
std::streambuf* buf;
bool disable_sync;
};
std::ostream& flush_on_endl(std::ostream& os)
{
os.iword(disable()) = false;
return os;
}
std::ostream& noflush_on_endl(std::ostream& os)
{
os.iword(disable()) = true;
return os;
}
std::ostream& endl(std::ostream& os)
{
syncing_buffer_optional eb(os);
os.rdbuf(&eb);
return os << std::endl;
}
int main()
{
std::cout << noflush_on_endl << endl;
}