应使用 std::cerr 输出错误信息,因其不缓冲且终端常高亮显示(如红色),便于快速区分和定位错误;调试信息、断言失败、参数校验失败等均应走 std::cerr,关键分支前也建议添加。

用 std::cerr 区分错误输出和正常输出
终端里混着看 std::cout 和报错信息,等于自己给自己埋雷。错误定位的第一步是让错误流“跳出来”——std::cerr 默认不缓冲,且通常被终端高亮(如红色),能立刻和普通输出区分开。
实操建议:
- 所有调试性错误信息、断言失败、参数校验失败,都走
std::cerr,别用std::cout - 在关键分支前加
std::cerr ,比打日志更轻量 - 注意:
std::cerr不自动 flush,但加std::endl或std::flush可确保实时看到(尤其程序崩溃前)
用 __FILE__ 和 __LINE__ 定位到具体代码位置
只打印“出错了”没用,必须知道错在哪一行哪一文件。C++ 预定义宏 __FILE__ 和 __LINE__ 是零成本定位工具,编译期展开,无运行时开销。
常见错误现象:自己写的 LOG_ERROR("failed") 调了十次,根本分不清是哪个调用点崩的。
实操建议:
- 封装一个简易宏:
#define DEBUG_LOG(msg) std::cerr - 避免在循环体里高频打
DEBUG_LOG,否则 I/O 成瓶颈;可加条件,如if (i == 5) DEBUG_LOG("i is 5"); - 注意:
__FILE__返回的是完整路径,若想只留文件名,可用strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__截取(需<cstring></cstring>)
崩溃时没输出?检查 std::cerr 是否被重定向或缓冲了
有时加了 std::cerr 却什么也看不到,不是没执行,而是输出卡在缓冲区,或被重定向到别处(比如 IDE 的某个隐藏通道、日志文件)。
实操建议:
- 崩溃前强制刷新:
std::cerr (<code>std::endl也带 flush,但略重) - 确认是否被重定向:在 main 开头加
std::cerr ,看终端是否立即出现;没出现就查启动命令或 IDE 运行配置 - Linux 下可临时用
./a.out 2>&1 | cat -n把 stderr 强制吐到管道并编号,避免被 IDE 吞掉
用 assert 捕获逻辑前提失效,而非仅靠输出猜
光靠 printf 式输出只能“事后观察”,而 assert 是主动拦截。它在 debug 模式下触发时会直接中止,并打印失败表达式和位置,比手写 if (!ptr) { std::cerr 更可靠。
使用场景:指针非空、数组索引不越界、函数前置条件成立等。
实操建议:
- 启用
-DNDEBUG前务必确认已过 debug 阶段;release 下assert全失效,不能替代运行时校验 - 不要在
assert里放有副作用的表达式,例如assert(x++ > 0)—— release 下 x 不会自增,行为不一致 - 对关键对象可加自检函数:
assert(vec.size() == vec.capacity() || "vector not full but expected");,字符串字面量会被assert自动转为失败消息
std::cerr 输出,往往因为没 flush 就消失了。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











