流类体系实现分析
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 实现 — 新的格式化方式
- std::print 实现 — 新的输出方式
---
## 延伸阅读
- [std::format 实现](/internals/io/format) — 新的格式化方式
- [std::print 实现](/internals/io/print) — 新的输出方式