You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

std::cout是如何实现的?protected构造下它如何被实例化?

关于std::cout实例化的疑问与解答

std::cout是std::ostream的实例,在GCC 7的头文件/usr/include/c++/7/iostream中可以看到它的声明:

extern ostream cout;      /// Linked to standard output

其中std::ostream是类型别名,本质是typedef std::basic_ostream<char> std::ostream。

尝试直接在用户代码中创建std::ostream实例会编译失败,测试代码如下:

#include<iostream>

int main()
{
    std::ostream os;
    return 0;
}

在GCC 4.9环境下编译上述代码,会抛出如下错误:

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的无参构造函数被标记为protected,用户代码没有权限调用,这就引出了核心疑问:标准库是如何创建std::cout实例的?

查阅公开的标准库文档,仅能找到关于std::cout的高层行为描述,没有说明具体实现逻辑:

全局对象std::cout和std::wcout控制输出到实现定义类型的流缓冲区(派生自std::streambuf),该缓冲区与标准C输出流stdout关联。

实现原理

这里的认知误区很容易被点破:受保护的仅仅是std::basic_ostream的无参构造函数,这个类还提供了公有的带参构造函数。
std::basic_ostream有一个公有构造函数,接收std::basic_streambuf类型的指针作为参数。标准库初始化std::cout时,根本不会调用那个受保护的无参构造:

  • 首先在标准库内部实现中,会先构造一个派生自std::basic_streambuf的自定义流缓冲区实例,这个缓冲区的内部逻辑封装了和C标准流stdout的交互,属于实现定义的内部类型,不对外暴露。
  • 之后将这个内部流缓冲区实例的指针作为参数,调用std::basic_ostream的公有构造函数,就完成了std::cout的初始化。

用户代码中直接写std::ostream os;会报错,是因为这个写法默认调用无参构造函数,而这个无参构造的设计初衷就是给标准库内部的派生流类(比如同时支持读写的std::iostream)使用的,普通用户本来就不应该创建没有绑定任何底层缓冲区的空std::ostream对象,所以被设计为protected权限完全合理。

注:上述分析思路由Nathan Pierson提供。

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 14:12:17