应使用 std::cout << __FILE__ << ":" << __LINE__ << " " << message << std::endl;,注意 __FILE__ 是字符串、__LINE__ 是整数,需用 << 拼接。

如何用 __FILE__ 和 __LINE__ 打印带位置信息的日志
直接在日志输出里拼接这两个宏,但别裸用——它们是字符串字面量和整数,std::cout 看似可行,实际会输出完整路径(比如 <code>"/home/user/proj/src/logger.cpp"),太长且不跨平台。更关键的是,__LINE__ 是整数,但日志常要格式化成一行字符串再写入文件或缓冲区,硬拼容易出类型错或临时对象生命周期问题。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 用
std::ostringstream或 C++20 的std::format组装消息,避免隐式转换风险 - 对
__FILE__做路径裁剪:只保留文件名,用std::string_view(__FILE__).substr(...)找最后一个'/'或'\' - 宏定义时用
do { ... } while(0)包裹,防止 if/else 分支下误展开 - 示例:
#define LOG_INFO(msg) do { std::string_view file = __FILE__; auto pos = file.find_last_of("/\"); file = (pos != std::string_view::npos) ? file.substr(pos+1) : file; std::ostringstream oss; oss << "[" << file << ":" << __LINE__ << "] " << msg; write_to_log(oss.str()); } while(0)
为什么不能把 __FILE__ 和 __LINE__ 直接塞进类成员函数参数
因为宏在预处理阶段展开,位置信息属于调用点,不是定义点。如果写一个 Logger::log(const char* file, int line, const char* msg),再在外部用 logger.log(__FILE__, __LINE__, "xxx"),看似合理,但实际破坏了封装性,每次调用都要手动传——没人会坚持这么做,迟早漏掉或写错。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 把宏封装成内联函数调用,比如
log_impl(__FILE__, __LINE__, msg),对外只暴露LOG_INFO("xxx")这种宏接口 - 避免在类内部保存
__FILE__字符串——它可能指向不同编译单元,长度不可控,且静态存储期下多线程写入会冲突 - 如果真要用成员函数接收位置信息,必须确保调用方始终用宏包裹,否则日志位置就失效了
__FILE__ 在头文件里展开会指向包含它的源文件,不是头文件本身
这是最常被忽略的一点。如果你把 LOG_INFO 宏定义在 logger.h 里,然后在 main.cpp 中 #include "logger.h" 并调用 LOG_INFO("test"),那么 __FILE__ 展开的是 "main.cpp",不是 "logger.h"。这其实是正确行为——日志该反映“谁在调用”,而不是“谁定义了宏”。
但要注意:
- 如果宏定义在头文件中,又用了
static inline辅助函数,函数体内再用__FILE__,那它还是指向头文件路径,不是调用点——因为函数体在头里,预处理时已固定 - 想让日志位置精准到调用行,所有逻辑必须在宏里展开,不能下沉到独立函数体内
- 跨模块共享日志宏时,确保头文件只含声明、不含实现,否则 ODR 违规
性能与线程安全的现实取舍
每次日志都做字符串拼接、路径裁剪、std::ostringstream 构造析构,开销不小。而加锁保护全局日志流又容易成为瓶颈。没有银弹,只有按场景选策略。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 调试期用全信息宏;发布版可条件编译去掉
__FILE__/__LINE__,或只保留文件名哈希值 - 避免在循环内高频打日志,尤其带位置信息的——宏展开后每行都是独立字符串构造
- 若需线程安全,优先用无锁环形缓冲区 + 单独日志线程消费,而不是给
std::ofstream加互斥量 - 不要用
std::cerr直接输出——它默认行缓冲,但在重定向到文件时可能变全缓冲,导致日志延迟或丢失
宏展开的位置信息看着简单,但一旦涉及头文件包含、模板实例化、链接时优化,__FILE__ 和 __LINE__ 的行为边界就很容易滑出去。最稳的方式,是让宏完全自洽,不依赖外部函数体里的预定义宏。



















