乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • C++ 学习路径
  • 第1章 C++概述与开发环境

    • C++ 语言概述与编译模型
    • 第一个 C++ 程序与规范
    • 开发环境配置
    • 预处理指令详解
  • 第2章 基本语法与类型系统

    • 变量与基本类型
    • 类型转换
    • 枚举类型
    • 引用与指针
    • 数组与 stdarray
    • 字符串与原始字符串字面量
    • const 与 constexpr
    • nullptr 与空指针
    • 类型推导 auto 与 decltype
    • 基于范围的 for 循环
    • 值类别全面解析
    • char16_t 与 char32_t
    • static_assert 编译期断言
  • 第3章 函数与重载

    • 函数声明与定义
    • 函数重载
    • 默认参数与内联函数
    • Lambda 表达式
    • 函数对象与 stdfunction
    • 后置返回类型与 noexcept
  • 第4章 类与对象

    • 类的基本定义
    • 构造函数与析构函数
    • 拷贝控制
    • 移动构造函数与移动赋值
    • 列表初始化与类内初始化器
    • 静态成员与嵌套类
    • 友元
    • =default 与 =delete
  • 第5章 继承与多态

    • 继承基础
    • 虚函数与多态
    • 虚函数表与动态绑定原理
    • 虚析构函数
    • 抽象类与纯虚函数
    • 多重继承与虚继承
    • 继承构造函数
  • 第6章 运算符重载

    • 运算符重载基础
    • 算术与关系运算符重载
    • 赋值与移动运算符重载
    • 特殊运算符重载
  • 第7章 模板与泛型编程

    • 函数模板
    • 类模板
    • 模板特化与偏特化
    • 可变参数模板
    • 别名模板与模板模板参数
    • SFINAE 与类型萃取
    • 依赖名与 typename/template 关键字
  • 第8章 异常处理

    • 异常处理机制
    • noexcept 与异常安全
    • RAII 与异常安全实践
  • 第9章 内存管理与智能指针

    • 动态内存与内存分区
    • RAII 惯用法
    • unique_ptr
    • shared_ptr 与 weak_ptr
    • 内存管理最佳实践
  • 第10章 右值引用与移动语义

    • 右值引用与值类别深度解析
    • std::move 原理与使用
    • 完美转发与 std::forward
    • 移动语义性能对比与最佳实践
  • 第11章 STL容器

    • vector 深度剖析
    • deque 内部机制
    • list 与 forward_list
    • map 与 set 深度解析
    • unordered 容器与哈希原理
    • array 与 tuple
    • 容器适配器
    • 容器选择全景指南
  • 第12章 STL算法与迭代器

    • 迭代器体系全解
    • 非变异算法
    • 变异算法
    • 排序与二分算法
    • Lambda 与算法组合
    • std::random 随机数库
    • 自定义迭代器开发
  • 第13章 IO流与文件

    • 标准 IO 流
    • 格式化输出控制
    • 文件流操作
    • 字符串流
    • std::regex 正则表达式
  • 第14章 并发与多线程

    • thread 基础与线程管理
    • mutex 与 lock_guard
    • unique_lock 与 condition_variable
    • thread_local 线程局部存储
    • atomic 与内存序
    • future 与 async 异步编程
    • std::chrono 时间库
  • 第15章 现代C++新特性

    • 从 C++11 到 C++20 演进路线
    • C++14 关键新特性
    • C++17 关键新特性
    • C++20 核心特性速览
  • 第16章 面试考点与最佳实践

    • C++ 综合最佳实践清单
    • 高频面试题精讲
    • 多线程面试题与实战
    • 内存管理常见陷阱与排查
  • 附录

    • C++ 核心知识点
    • C++ 专业术语

标准 IO 流

定义与作用

标准 IO 流提供控制台输入输出的抽象层。四个预定义流对象连接标准输入输出通道:

std::cin   >> x;   // 标准输入  (stdin)
std::cout  << x;   // 标准输出  (stdout,缓冲)
std::cerr  << x;   // 标准错误  (stderr,无缓冲)
std::clog  << x;   // 标准日志  (stderr,缓冲)

核心原理

流继承体系

流状态位

完整示例

示例一:飞翔科技运维监控面板输入

场景说明:李眉编写一个交互式终端程序,演示 cin 安全读取和流状态管理。

#include <iostream>
#include <limits>
#include <string>
#include <iomanip>

void clearInputBuffer() {
    std::cin.clear();  // 清除错误标志
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

int main() {
    std::cout << "=== 飞翔科技运维监控面板 ===\n\n";

    // 1. 基本输入 —— 使用 while(cin) 循环
    std::cout << "请输入多条服务器地址 (输入空行结束):\n";
    std::string server;
    int count = 0;
    while (std::getline(std::cin, server) && !server.empty()) {
        std::cout << "  [" << ++count << "] 已添加: " << server << "\n";
    }
    std::cout << "共录入 " << count << " 台服务器\n\n";

    // 2. 错误处理 —— 输入非数字时恢复
    int threshold;
    while (true) {
        std::cout << "输入告警阈值 (整数): ";
        if (std::cin >> threshold) {
            std::cout << "阈值已设置: " << threshold << "%\n";
            break;
        }
        std::cerr << "[错误] 请输入有效的整数!\n";
        clearInputBuffer();
    }

    // 3. 混合输入 —— 数字和字符串交替
    clearInputBuffer();  // 清除 >> 后残留的换行
    std::cout << "\n输入监控项 (格式: 名称 CPU占比):\n";
    std::string itemName;
    double cpuUsage;
    std::cout << "> ";
    std::cin >> itemName >> cpuUsage;
    std::cout << "监控项: " << itemName << " CPU=" << cpuUsage << "%\n";

    // 4. cerr vs clog
    std::cerr << "[cerr] 立即输出(无缓冲)—— 紧急告警!\n";
    std::clog << "[clog] 缓冲输出 —— 常规日志\n";
    std::cout << "--- 日志分隔线 ---\n";

    // 5. 检查流状态
    std::cout << "\n流状态检查:\n";
    std::cout << "  cin.good(): " << std::cin.good() << "\n";
    std::cout << "  cin.eof():  " << std::cin.eof() << "\n";
    std::cout << "  cin.fail(): " << std::cin.fail() << "\n";
}

预期输出(示例交互):

=== 飞翔科技运维监控面板 ===

请输入多条服务器地址 (输入空行结束):
192.168.1.101
  [1] 已添加: 192.168.1.101
192.168.1.102
  [2] 已添加: 192.168.1.102

共录入 2 台服务器

输入告警阈值 (整数): 八十五
[错误] 请输入有效的整数!
输入告警阈值 (整数): 85
阈值已设置: 85%

输入监控项 (格式: 名称 CPU占比):
> web-server-01 62.5
监控项: web-server-01 CPU=62.5%
[cerr] 立即输出(无缓冲)—— 紧急告警!
[clog] 缓冲输出 —— 常规日志
--- 日志分隔线 ---

流状态检查:
  cin.good(): 1
  cin.eof():  0
  cin.fail(): 0

逐段分析:

  • std::getline(cin, s) 读取整行,适合含空格的输入
  • cin.clear() 清除错误标志后 cin 才能继续使用
  • cin.ignore(...) 丢弃缓冲区残留,避免混合 >> 和 getline 时的问题
  • cerr 无缓冲,适合紧急告警;clog 有缓冲,适合日志记录
  • 流支持隐式转为 bool:if (cin) 等价于 if (!cin.fail())

示例二:sync_with_stdio 性能对比

场景说明:白歌测试 sync_with_stdio 对大数据量 IO 的性能影响。

#include <iostream>
#include <chrono>
#include <cstdio>

int main() {
    const int N = 1'000'000;

    // 测试1:默认(与 C stdio 同步)
    auto start1 = std::chrono::steady_clock::now();
    for (int i = 0; i < N; ++i)
        std::cout << i << '\n';
    auto end1 = std::chrono::steady_clock::now();
    auto t1 = std::chrono::duration_cast<std::chrono::milliseconds>(end1 - start1);

    // 测试2:关闭同步
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);  // 解除 cin 和 cout 的绑定

    auto start2 = std::chrono::steady_clock::now();
    for (int i = 0; i < N; ++i)
        std::cout << i << '\n';
    auto end2 = std::chrono::steady_clock::now();
    auto t2 = std::chrono::duration_cast<std::chrono::milliseconds>(end2 - start2);

    // 恢复同步
    std::ios::sync_with_stdio(true);

    std::cout << "\n=== 飞翔科技 IO 性能测试 ===\n";
    std::cout << "输出 " << N << " 个整数:\n";
    std::cout << "  同步开启: " << t1.count() << " ms\n";
    std::cout << "  同步关闭: " << t2.count() << " ms\n";
    std::cout << "  加速比: " << std::fixed << std::setprecision(1)
              << (double)t1.count() / t2.count() << "x\n";

    std::cout << "\n注意: 关闭同步后不能混用 C++ cout 和 C printf/scanf\n";
}

预期输出(数值因环境而异):

(输出一百万行整数...)

=== 飞翔科技 IO 性能测试 ===
输出 1000000 个整数:
  同步开启: 3421 ms
  同步关闭: 1287 ms
  加速比: 2.7x

注意: 关闭同步后不能混用 C++ cout 和 C printf/scanf

逐段分析:

  • sync_with_stdio(false) 关闭 C++ 流与 C stdio 的内部同步,大幅提升性能
  • 关闭后 C++ 流使用独立缓冲区,不能与 printf/scanf 混用
  • cin.tie(nullptr) 解绑 cin 和 cout,避免每次输入前自动刷新输出缓冲
  • 建议在 main 函数开始时调用,且之后不能再改回

易错场景与面试考点

易错场景

1. >> 后残留换行导致 getline 行为异常

int age;
std::cin >> age;               // 输入 "25\n"
std::string name;
std::getline(std::cin, name);  // 直接读取到残留的 "\n",name 为空!
// 解决:cin.ignore() 清除换行

2. cerr 和 clog 输出可能交叉

// 由于缓冲策略不同,cerr 和 clog 的输出顺序可能不如预期
std::clog << "A";
std::cerr << "B";
std::clog << "C";  // "BAC" 还是 "ABC" 不确定

3. cin 失败后不清理状态

int x;
while (!(std::cin >> x)) {
    // ❌ 如果没有 cin.clear() + ignore(),cin 永远失败
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

面试考点

考点要点
四标准流cin/stdin, cout/stdout(缓冲), cerr/stderr(无缓冲), clog/stderr(缓冲)
流状态位goodbit/eofbit/failbit/badbit,组合使用
operator boolwhile(cin >> x) 检测 fail(),EOF 时也退出
sync_with_stdio默认与 C stdio 同步,关闭可提速 2-10 倍
cin.tiecin 默认绑定 cout,每次读取前刷新 cout
getline vs >>getline 读行含空格,>> 按空白字符分割
错误恢复clear() + ignore() 是标准恢复模式
下一页
格式化输出控制