Skip to content

流类体系实现分析

C++ 流类体系是传统的 I/O 框架,提供类型安全的输入输出。本文基于 GCC 和 LLVM 的源码,分析流类体系的内部实现。


一、核心概念

1.1 流类层次

流类层次:

ios_base
  └── basic_ios<CharT>
        └── basic_ostream<CharT>  ← 输出流
        └── basic_istream<CharT>  ← 输入流
              └── basic_iostream<CharT>  ← 输入输出流

具体流类:
  · basic_filestream  ← 文件流
  · basic_stringstream  ← 字符串流
  · basic_fstream  ← 文件流

1.2 streambuf 的角色

streambuf 的角色:

streambuf 是流的底层缓冲区管理器:
  · 管理输入/输出缓冲区
  · 处理格式化
  · 与外部设备交互

具体 streambuf:
  · filebuf  ← 文件缓冲区
  · stringbuf  ← 字符串缓冲区
  · cout 等全局对象使用特殊的 streambuf

二、GCC (libstdc++) 的实现

2.1 basic_ostream 的实现(源码分析)

cpp
// 源码路径:references/impl/gcc/libstdc++-v3/include/ostream

// 输出流的基类
template<typename _CharT, typename _Traits>
class basic_ostream : virtual public basic_ios<_CharT, _Traits> {
public:
    // 插入运算符(基本类型)
    basic_ostream& operator<<(int __n) {
        // 调用 streambuf::sputn 或单字符输出
        this->_M_insert(__n);
        return *this;
    }
    
    // 插入运算符(字符串)
    basic_ostream& operator<<(const char* __s) {
        this->_M_insert(__s);
        return *this;
    }
    
    // 插入运算符(流操纵器)
    basic_ostream& operator<<(ostream& (*__pf)(ostream&)) {
        return __pf(*this);
    }
    
    // 输出单个字符
    basic_ostream& put(char_type __c) {
        this->rdbuf()->sputc(__c);
        return *this;
    }
    
    // 写入多个字符
    basic_ostream& write(const char_type* __s, streamsize __n) {
        this->rdbuf()->sputn(__s, __n);
        return *this;
    }
    
    // 刷新缓冲区
    basic_ostream& flush() {
        this->rdbuf()->pubsync();
        return *this;
    }
};

2.2 basic_streambuf 的实现(源码分析)

cpp
// 源码路径:references/impl/gcc/libstdc++-v3/include/streambuf

// streambuf 的核心接口
template<typename _CharT, typename _Traits>
class basic_streambuf {
protected:
    // 缓冲区指针
    char_type* _M_in_beg;   // 输入缓冲区起始
    char_type* _M_in_cur;   // 输入缓冲区当前位置
    char_type* _M_in_end;   // 输入缓冲区结束
    char_type* _M_out_beg;  // 输出缓冲区起始
    char_type* _M_out_cur;  // 输出缓冲区当前位置
    char_type* _M_out_end;  // 输出缓冲区结束
    
public:
    // 输出单个字符
    virtual int_type sputc(char_type __c) {
        if (_M_out_cur != _M_out_end) {
            *_M_out_cur++ = __c;
            return __c;
        }
        return this->overflow(__c);
    }
    
    // 输出多个字符
    virtual streamsize sputn(const char_type* __s, streamsize __n) {
        // 尝试直接输出
        streamsize __put = std::min(__n, _M_out_end - _M_out_cur);
        traits_type::copy(_M_out_cur, __s, __put);
        _M_out_cur += __put;
        
        // 如果还有剩余,调用 overflow
        if (__put < __n) {
            this->overflow(__s[__put], __n - __put);
        }
        return __n;
    }
    
    // 输出缓冲区满时调用
    virtual int_type overflow(int_type __c = traits_type::eof()) {
        // 子类实现具体的缓冲区管理
        return traits_type::not_eof(__c);
    }
    
    // 同步缓冲区
    virtual int sync() {
        // 子类实现具体的同步逻辑
        return 0;
    }
};

三、GCC vs LLVM 差异对比

┌────────────────────────┬──────────────────────┬──────────────────────┐
│ 特性                    │ GCC (libstdc++)      │ LLVM (libc++)        │
├────────────────────────┼──────────────────────┼──────────────────────┤
│ basic_ostream          │ 完整                 │ 完整                 │
│ basic_istream          │ 完整                 │ 完整                 │
│ basic_filestream       │ 完整                 │ 完整                 │
│ basic_stringstream     │ 完整                 │ 完整                 │
│ streambuf              │ 完整                 │ 完整                 │
│ locale 集成            │ 完整                 │ 完整                 │
│ format 集成            │ C++20                │ C++20                │
└────────────────────────┴──────────────────────┴──────────────────────┘

延伸阅读


---

## 延伸阅读

- [std::format 实现](/internals/io/format) — 新的格式化方式
- [std::print 实现](/internals/io/print) — 新的输出方式

基于 MIT 许可发布