std::cout是std::ostream的一个实例。我可以在一个名为usr/include/c/7/iostream的文件中看到std::cout的声明:
extern ostream cout; /// Linked to standard output
而std::ostream由typedef std::basic\u ostream定义
此外,您似乎无法创建std::ostream的实例。请参阅此演示代码片段:
#include<iostream>
int main()
{
std::ostream os;
return 0;
}
以下是编译器对上述代码段的抱怨:
In file included from /opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/iostream:39:0,
from <source>:1:
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/ostream: In function 'int main()':
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/ostream:384:7: error: 'std::basic_ostream<_CharT, _Traits>::basic_ostream() [with _CharT = char; _Traits = std::char_traits<char>]' is protected
basic_ostream()
^
<source>:5:18: error: within this context
std::ostream os;
^
问题来了,因为std::basic_ostream
CppReference上的这个链接似乎没有什么意义。它没有清楚地告诉我如何实现std::cout,以及std::ostream的构造函数如何创建std::cout。据我所知,最相关的信息是:
全局对象控制到与标准C输出流关联的实现定义类型的流缓冲区的输出(派生自标准C输出流)。
没什么了。
我正在使用gcc 4.9开发Ubuntu
感谢@NathanPierson。
他告诉我的
std::basic_ostream
有一个构造函数,它接受指向std::basic_streambuf
对象的指针。std::cout
使用指向std::basic_streambuf
的某个实现定义的派生类的实例的指针进行初始化。
,这让我更接近答案。
编译器及其标准库实现可以使用程序员无法使用的非标准特性进行协作。
这在这种情况下是不必要的,因为有一个相当标准的公共构造函数:
explicit basic_ostream(basic_streambuf<char_type, Traits>* sb);
如果您准备好了stream buf
,您可以创建ostream
类型的对象,标准库也是如此。
streambuf实际上是一个隐藏的实现细节,但在典型的实现中,它可能是由stdout(C样式)构造的自定义类的对象
std::c是如何创建的?
首先,从https://en.cppreference.com/w/cpp/io/ios_base/Init开始:
d::ios_base::初始化
此类用于确保正确初始化和销毁默认C流(std::cin、std::cout等)。[...]
标头的行为就好像它定义了(直接或间接)std::ios\u base::Init的实例,静态存储持续时间:[…]
Meh,让我们做一个真实的代码示例。我将使用GCC C库。从…起https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/include/std/iostream#L73,这是重要的部分:
// For construction of filebuffers for cout, cin, cerr, clog et. al.
static ios_base::Init __ioinit;
现在我们跳到ios\u base::Init类的contsructor,在https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/src/c++98/ios\u init。抄送#L85:
ios_base::Init::Init()
{
if (__gnu_cxx::__exchange_and_add_dispatch(&_S_refcount, 1) == 0)
{
// Standard streams default to synced with "C" operations.
_S_synced_with_stdio = true;
new (&buf_cout_sync) stdio_sync_filebuf<char>(stdout);
new (&buf_cin_sync) stdio_sync_filebuf<char>(stdin);
new (&buf_cerr_sync) stdio_sync_filebuf<char>(stderr);
// The standard streams are constructed once only and never
// destroyed.
new (&cout) ostream(&buf_cout_sync);
new (&cin) istream(&buf_cin_sync);
new (&cerr) ostream(&buf_cerr_sync);
new (&clog) ostream(&buf_cerr_sync);
cin.tie(&cout);
cerr.setf(ios_base::unitbuf);
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 455. cerr::tie() and wcerr::tie() are overspecified.
cerr.tie(&cout);
当您调用ios\u base::Init::Init()时,S\u refcount就在那里 从静态类的构造函数手动执行,它可以防止双重初始化。
stdio\u sync\u filebuf是一个内部缓冲区,用于存储输入/输出数据,在这里实现https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/include/ext/stdio\u sync\u filebuf。h#L56。它继承自std::basic\u streambuf。
因此,可以使用stdio\u sync\u filebuf就地构建
现在,因为这些东西是就地html" target="_blank">构建的,您可能想知道内存是如何分配的?从…起https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/src/c++98/globals\u io。抄送#L50:
// Standard stream objects.
// NB: Iff <iostream> is included, these definitions become wonky.
typedef char fake_istream[sizeof(istream)]
__attribute__ ((aligned(__alignof__(istream))));
typedef char fake_ostream[sizeof(ostream)]
__attribute__ ((aligned(__alignof__(ostream))));
fake_istream cin;
fake_ostream cout;
fake_ostream cerr;
fake_ostream clog;
对象只是空的缓冲区,大小和对齐方式都合适。
是的,您可以使用GCC上的stdio\u sync\u filebuf构建ostream:
#include <fstream>
#include <ext/stdio_sync_filebuf.h>
int main() {
__gnu_cxx::stdio_sync_filebuf<char> mybuf_cout_sync(stdout);
std::ostream os(&mybuf_cout_sync);
os << "Hello world!\n";
return 0;
}
或者,为了可移植,您可以编写自己的继承自std::stream buf
的类,并自己构建ostream
。网上有很多例子,比如这里https://stackoverflow.com/a/51250032/9072753。
这是一个算法来自https://en.cppreference.com/w/cpp/algorithm/random_shuffle: > 为什么使用声明在循环体内部而不是外部?将其留在内部(迭代)会影响性能吗?谢谢!
我需要弄清楚lock和condition_variable是如何工作的。 在这里略有修改的cplusplusreference代码中 我感到困惑的是,如果worker_thread已经锁定了互斥体,主线程如何锁定它。 我不明白为什么在这种情况下会出现“运行时错误”。
下面的代码显示了我要做的:
我在下面声明std: map: 但是我有很多错误,比如: 错误16错误C2676:二进制' 我做错了什么?
我不知道如何创建以下内容: 我总是得到 /usr/include/c/5.5.0/bits/stl_对。h:139:45:错误:使用已删除的函数'std::atomic::atomic(const std::atomic 我已经试过了 我知道std::atomic是不可复制的,那么你应该如何创建一对呢?难道这不可能吗?
我尝试使用Tokio库在生锈中初始化具有异步功能的服务器: 这会抛出一个错误,表示: 当我将鼠标悬停在<code>侦听器</code>上时,其类型未知。