如何制作一个不刷新 std::cout 的简单 C++ 程序
How to make a simple C++ program in which std::cout is not flushed
为了更好地理解 C++ 中的缓冲流,我想编写一个简单的程序,其中 std::cout
缓冲区在终止前不会被刷新。因为我已经读到 std::cout
在正常终止时被刷新,所以我尝试抛出运行时错误。我也避免使用 std::endl
,因为我知道这会强制刷新。第一次尝试:
//file noflush.cpp
#include <iostream>
int main() {
std::cout << "Don't write me to the console!";
throw 0;
}
用g++编译,从终端调用:
$ ./noflush
libc++abi.dylib: terminating with uncaught exception of type int
Don't write me to the console!Abort trap: 6
即使我强制执行运行时错误,缓冲区似乎仍会在终止时被刷新。是否可以 "strand" 缓冲区中的一些数据,而不将其写入设备?
通过以下示例,我可以使用 gcc 4.8.3 创建您想要的行为:
#include <iostream>
#include <vector>
int main()
{
std::string str;
for(unsigned long int i = 0; i < 10000; ++i)
str += "Hello ! ";
str += "END";
std::cout << str;
std::vector<double>* p;
p->push_back(1.0);
delete p;
std::cout << "STILL ALIVE !" << std::endl;
return 0;
}
那么,输出是:
Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! [...] Hello ! Segmentation fault
我们可以看到 END
在分段错误之前没有打印出来。
这不是标准的c++,但是在POSIX、中你可以发送一个"kill"信号来杀死运行进程。这将停止执行而不进行清理,例如刷新缓冲区。
编辑:我意识到信号不仅是 POSIX,而且实际上是 C 标准库的一部分(并包含在 C++ 标准库中)。
#include <csignal>
// ...
std::cout << "Don't write me to the console!";
std::raise(SIGKILL);
据我所知,在程序终止之前,没有标准的兼容和干净的方法来避免 std::cout
到 flush()
(但是,当然,你可以使用不干净的方法,例如提高一个信号 or ). According to cppreference, the actual buffer type controlled by std::cout
is implementation defined but derived from std::streambuf
,它似乎不允许 public 以模拟无声吞噬缓冲区的方式进行访问。
此外,正如我在评论中指出的那样,即使程序异常终止(通过 std::terminate()
或 std::abort()
也可能会或可能不会关闭打开的资源,因此这又是实现定义的。
如果我没看错,您想捕获或忽略 std::cout
:
的输出
#include <iostream>
#include <sstream>
int main()
{
// Capture the output to `std::cout`
{
std::cout << "[Capture Output]" << std::endl;
std::stringstream cpature;
auto restore = std::cout.rdbuf(cpature.rdbuf());
std::cout << "... captured output ..." << std::endl;
std::cout.rdbuf(restore);
std::cout << "[Enable Output]" << std::endl;
// Display the cpatured output.
std::cout << cpature.rdbuf();
}
std::cout << std::endl;
// Even more drasticly: Ignore the output to `std::cout`
{
std::cout << "[Ignore Output]" << std::endl;
auto restore = std::cout.rdbuf(nullptr);
std::cout << "... ignored output ..." << std::endl;
std::cout.rdbuf(restore);
std::cout << "[Enable Output]" << std::endl;
}
std::cout << "[End]\n";
}
#include <iostream>
#include <sstream>
#include <vector>
int main()
{
std::stringstream cpature;
auto restore = std::cout.rdbuf(cpature.rdbuf());
std::cout.rdbuf(restore);
for(unsigned long int i = 0; i < 10000; ++i)
std::cout <<"Hello ! " << std::endl;
std::cout << "END" << std::endl;
std::cout << cpature.rdbuf();
std::vector<double> *p;
p->push_back(1.0);
delete p;
std::cout << "STILL ALIVE !" << std::endl;
}
为了更好地理解 C++ 中的缓冲流,我想编写一个简单的程序,其中 std::cout
缓冲区在终止前不会被刷新。因为我已经读到 std::cout
在正常终止时被刷新,所以我尝试抛出运行时错误。我也避免使用 std::endl
,因为我知道这会强制刷新。第一次尝试:
//file noflush.cpp
#include <iostream>
int main() {
std::cout << "Don't write me to the console!";
throw 0;
}
用g++编译,从终端调用:
$ ./noflush
libc++abi.dylib: terminating with uncaught exception of type int
Don't write me to the console!Abort trap: 6
即使我强制执行运行时错误,缓冲区似乎仍会在终止时被刷新。是否可以 "strand" 缓冲区中的一些数据,而不将其写入设备?
通过以下示例,我可以使用 gcc 4.8.3 创建您想要的行为:
#include <iostream>
#include <vector>
int main()
{
std::string str;
for(unsigned long int i = 0; i < 10000; ++i)
str += "Hello ! ";
str += "END";
std::cout << str;
std::vector<double>* p;
p->push_back(1.0);
delete p;
std::cout << "STILL ALIVE !" << std::endl;
return 0;
}
那么,输出是:
Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! Hello ! [...] Hello ! Segmentation fault
我们可以看到 END
在分段错误之前没有打印出来。
这不是标准的c++,但是在POSIX、中你可以发送一个"kill"信号来杀死运行进程。这将停止执行而不进行清理,例如刷新缓冲区。
编辑:我意识到信号不仅是 POSIX,而且实际上是 C 标准库的一部分(并包含在 C++ 标准库中)。
#include <csignal>
// ...
std::cout << "Don't write me to the console!";
std::raise(SIGKILL);
据我所知,在程序终止之前,没有标准的兼容和干净的方法来避免 std::cout
到 flush()
(但是,当然,你可以使用不干净的方法,例如提高一个信号 std::cout
is implementation defined but derived from std::streambuf
,它似乎不允许 public 以模拟无声吞噬缓冲区的方式进行访问。
此外,正如我在评论中指出的那样,即使程序异常终止(通过 std::terminate()
或 std::abort()
也可能会或可能不会关闭打开的资源,因此这又是实现定义的。
如果我没看错,您想捕获或忽略 std::cout
:
#include <iostream>
#include <sstream>
int main()
{
// Capture the output to `std::cout`
{
std::cout << "[Capture Output]" << std::endl;
std::stringstream cpature;
auto restore = std::cout.rdbuf(cpature.rdbuf());
std::cout << "... captured output ..." << std::endl;
std::cout.rdbuf(restore);
std::cout << "[Enable Output]" << std::endl;
// Display the cpatured output.
std::cout << cpature.rdbuf();
}
std::cout << std::endl;
// Even more drasticly: Ignore the output to `std::cout`
{
std::cout << "[Ignore Output]" << std::endl;
auto restore = std::cout.rdbuf(nullptr);
std::cout << "... ignored output ..." << std::endl;
std::cout.rdbuf(restore);
std::cout << "[Enable Output]" << std::endl;
}
std::cout << "[End]\n";
}
#include <iostream>
#include <sstream>
#include <vector>
int main()
{
std::stringstream cpature;
auto restore = std::cout.rdbuf(cpature.rdbuf());
std::cout.rdbuf(restore);
for(unsigned long int i = 0; i < 10000; ++i)
std::cout <<"Hello ! " << std::endl;
std::cout << "END" << std::endl;
std::cout << cpature.rdbuf();
std::vector<double> *p;
p->push_back(1.0);
delete p;
std::cout << "STILL ALIVE !" << std::endl;
}