C++如何获取当前函数名和行号 _ 预定义宏与source_location【干货】
C++20的std::source_location通过显式调用current()方法,能够可靠地获取函数名与行号信息,相比依赖__func__等宏更加可靠。旧标准使用__func__等预定义宏,但存在不能取地址、宏展开时返回定义处函数名等陷阱,使用时需注意编译器版本。推荐使用C++20新特性,规避宏陷阱。
直接说结论:C++20 用 std::source_location 最可靠;老标准只能靠预定义宏(__func__、__FILE__、__LINE__),但这些宏本质上是编译器注入的静态字符数组,既不是函数调用,也不能传参或延迟求值,稍不注意就踩坑。下面展开聊聊,到底怎么回事。
为什么 __func__ 不是标准函数,也不能取地址
__func__ 是编译器在每个函数作用域内自动注入的静态字符数组,比如 static const char __func__[] = "foo";。它本质上是个隐含的局部变量,但它的行为很特殊——不能参与常规的表达式求值时机控制。
- 不能写
&__func__—— 编译会直接报错:address of function '__func__' cannot be taken。这意味它无法被当作正常变量来取地址或传递。 - 不能作为参数直接传给模板函数,除非模板显式接受
const char*且实参处于字面量上下文。普通传参很容易触发编译错误或不预期行为。 - 最大的陷阱在宏里:
__func__在宏展开时,始终返回宏定义处的函数名,而不是调用处的函数名。这导致很多人在日志宏里误用,结果打印出来的函数名永远是宏定义所在的那个函数,完全不是预期的。
std::source_location 怎么用才不掉坑
它是 C++20 引入的轻量结构体,通过编译器内置支持生成调用点信息(函数名、文件、行号、列号)。关键点在于:它默认构造时捕获的是调用点,而不是定义点。但前提是——你必须显式调用 ::current() 方法。
- 必须显式传递,默认不会自动注入。正确写法是:
log("msg", std::source_location::current()),别漏掉::current()。很多人会写成std::source_location loc;,然后直接传loc,结果初始化成无效值,line() == 0,function_name()返回空字符串——白忙一场。 - 性能几乎无开销:编译期填入常量,不涉及运行时调用或字符串拷贝。这比运行时拼字符串高效得多。
- 注意编译器版本:MSVC 2019 v16.8+、GCC 10+、Clang 11+ 才完整支持这个特性。低版本可能只返回空字符串或行号 0,调试时务必确认编译环境。
void log(const char* msg, const std::source_location& loc = std::source_location::current()) { std::cout << loc.file_name() << ":" << loc.line() << " [" << loc.function_name() << "] " << msg << "\n";}// 调用处自动捕获当前行和函数名log("start processing"); // 输出:main.cpp:42 [main] start processing
预定义宏在日志宏里的典型误用与修复
很多人写日志宏时直接拼接 __FILE__ 和 __LINE__,却忽略了宏展开时机问题——它们总在宏体内部展开,而不是调用位置。这是个常见的翻车现场。
- 错误写法:
#define LOG(x) std::cerr << __FILE__ << ":" << __LINE__ << x—— 总显示宏定义所在行,而不是调用处。 - 正确做法:用
__FILE__和__LINE__作为宏参数透传,或改用std::source_location。如果必须兼容 C++17,可以这样修:#define LOG(x) do { ::log_impl(x, __FILE__, __LINE__, __func__); } while(0),这样宏参数会在调用处展开,获取正确信息。 __FUNCTION__和__PRETTY_FUNCTION__是 GCC/Clang 扩展,前者等价于__func__,后者包含函数签名(如void foo(int)),但不可移植,跨平台项目慎用。
话说回来,真正麻烦的从来不是“怎么拿到名字”,而是“拿到的是哪一层的名字”——宏、内联、模板实例化、lambda 都会让 __func__ 或 source_location 指向意料之外的位置。调试时多打几行 std::source_location::current() 对比,比查文档更快定位问题。

WPS Office是一款面向macOS用户的综合办公套件,将文字处理、电子表格、演示文稿、PDF工具、模板与云协作整合在同一应用中。它兼容常见Microsoft Office格式,支持Intel及Apple芯片Mac,基础功能可免费使用,
Shapr3D是一款面向工业设计、机械工程、建筑概念和三维打印工作流的CAD软件。Mac版采用Parasolid建模内核,支持草图约束、实体建模、工程图、可视化渲染及常见CAD格式交换,并可通过账户在多台设备之间同步项目。
REAPER是Cockos开发的数字音频工作站,提供多轨音频与MIDI录制、剪辑、处理、混音和母带制作工具。Mac版兼容Intel与Apple芯片,支持AU、VST、VST3、CLAP等插件格式,并提供高度可定制的工作流程。
Adobe Photoshop 是面向摄影师、设计师和内容创作者的专业图像处理工具,可在 Windows 上完成照片修饰、选区抠图、图层合成、文字排版、绘画及生成式编辑。软件采用订阅授权,由 Creative Cloud 管理安装、更新与许
Adobe InDesign 是面向印刷与数字出版的专业页面排版工具,可制作书籍、杂志、宣传册、海报、交互式 PDF 和电子书。它提供精细的文字样式、多页面管理、印前检查及多格式输出能力,并能与 Photoshop、Illustrator
Adobe Illustrator 是用于绘制矢量图形、插画、图标、徽标和版式的专业设计工具。它以路径和锚点为核心,作品放大后仍能保持清晰,并提供画板、文字、渐变、图像描摹及精确变换等功能,适合品牌视觉、印刷物料、数字界面和商业插画创作。













