C++中的std::source_location有什么用?(获取代码文件名和行号)
发布时间 - 2026-01-09 00:00:00 点击率:次std::source_location 是什么,能直接替代 __FILE__ 和 __LINE__ 吗?
std::source_location 是 C++20 引入的标准设施,用于在编译期捕获调用点的源码位置信息。它不是宏,而是一个轻量值类型,包含 file_name()、line()、column() 和 function_name() 四个只读访问函数。它不能直接替代 __FILE__ 和 __LINE__ 的宏展开行为——因为 std::source_location::current() 是一个函数调用,其返回值反映的是该函数被调用处的位置,而非宏定义处。
常见误用是把它写*局变量或静态常量初始化:
static const auto loc = std::source_location::current(); // ❌ 错!总指向这行
正确做法是让它作为函数参数默认值,在每次调用时自动注入实际调用点信息。
怎么让日志函数自动记录调用位置?
最典型用途是为日志、断言、调试工具注入上下文。关键在于把 std::source_location 设为带默认值的函数参数:
- 默认值必须是
std::source_location::current(),
不能加括号以外的任何表达式(如 std::source_location{}会固定为定义处) - 参数必须按值传递(它是 trivially copyable,无开销)
- 不能是模板参数推导目标(它不参与重载/推导)
示例:
void log(const char* msg, std::source_location loc = std::source_location::current()) {
fprintf(stderr, "[%s:%d] %s\n", loc.file_name(), loc.line(), msg);
}
// 调用方完全无感知:
log("buffer overflow"); // 自动捕获这一行的文件和行号为什么 function_name() 返回的不是完整签名,且内容不可移植?
function_name() 返回的是编译器生成的符号名(mangled name),标准只要求它“尽可能描述调用点所在函数”,不保证可读性或跨编译器一致。GCC 可能返回 "void foo()",Clang 可能返回 "foo",MSVC 可能返回 。
如果你需要稳定可读的函数名:
- 不要依赖
function_name()做逻辑判断(比如 switch 或 if 比较) - 调试输出可以保留,但日志归类、监控告警等生产场景应避免用它做 key
- 真正需要符号名解析时,应结合外部工具(如 addr2line、llvm-symbolizer)或 ABI 解析库
和 assert / static_assert 有什么关系?
std::source_location 和 assert 没有直接集成,C++23 才引入 std::assertion_handler 支持自定义断言处理,但目前主流标准库(libstdc++、libc++、MSVC STL)的 assert 仍基于传统宏,输出由预处理器决定。
你可以自己封装断言宏来桥接:
#define MY_ASSERT(x) do { \
if (!(x)) { \
log_assert(#x, std::source_location::current()); \
std::abort(); \
} \
} while(0)
void log_assert(const char* expr, std::source_location loc) {
fprintf(stderr, "Assertion failed: %s at %s:%d\n", expr, loc.file_name(), loc.line());
}
注意:宏里调用 std::source_location::current() 是安全的,因为宏展开后它出现在调用点,不是宏定义内部。
真正容易被忽略的是:std::source_location 在 constexpr 函数中无法使用 current()(编译期无法确定“调用点”),所以它只适用于运行时上下文;另外,某些嵌入式或 freestanding 环境可能未实现该特性,需检查 __cpp_lib_source_location 宏。
# 工具
# c++
# overflow
# 为什么
# 常量
# 全局变量
# void
# 值类型
# 值传递
# column
# 的是
# 默认值
# 行号
# 而非
# 是一个
# 如果你
# 你可以
# 出现在
# 设为
# 适用于
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel怎么解决跨域问题_Laravel配置CORS跨域访问
动图在线制作网站有哪些,滑动动图图集怎么做?
通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】
如何在IIS中新建站点并解决端口绑定冲突?
Linux系统命令中screen命令详解
海南网站制作公司有哪些,海口网是哪家的?
如何在IIS管理器中快速创建并配置网站?
CSS3怎么给轮播图加过渡动画_transition加transform实现【技巧】
javascript基本数据类型及类型检测常用方法小结
nginx修改上传文件大小限制的方法
高性能网站服务器部署指南:稳定运行与安全配置优化方案
个人摄影网站制作流程,摄影爱好者都去什么网站?
mc皮肤壁纸制作器,苹果平板怎么设置自己想要的壁纸我的世界?
在线制作视频的网站有哪些,电脑如何制作视频短片?
Laravel Blade组件怎么用_Laravel可复用视图组件的创建与使用
悟空浏览器如何设置小说背景色_悟空浏览器背景色设置【方法】
Windows Hello人脸识别突然无法使用
phpredis提高消息队列的实时性方法(推荐)
西安专业网站制作公司有哪些,陕西省建行官方网站?
如何生成腾讯云建站专用兑换码?
Laravel怎么上传文件_Laravel图片上传及存储配置
html5源代码发行怎么设置权限_访问权限控制方法与实践【指南】
nodejs redis 发布订阅机制封装实现方法及实例代码
JS弹性运动实现方法分析
学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?
Laravel如何实现数据库事务?(DB Facade示例)
活动邀请函制作网站有哪些,活动邀请函文案?
Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理
详解Android中Activity的四大启动模式实验简述
Laravel怎么实现一对多关联查询_Laravel Eloquent模型关系定义与预加载【实战】
Android实现代码画虚线边框背景效果
EditPlus中的正则表达式实战(5)
如何在阿里云通过域名搭建网站?
Laravel Fortify是什么,和Jetstream有什么关系
ai格式如何转html_将AI设计稿转换为HTML页面流程【页面】
Python结构化数据采集_字段抽取解析【教程】
在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?
如何用PHP快速搭建CMS系统?
如何用y主机助手快速搭建网站?
如何在Windows服务器上快速搭建网站?
实例解析angularjs的filter过滤器
图册素材网站设计制作软件,图册的导出方式有几种?
企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?
高防服务器租用如何选择配置与防御等级?
大型企业网站制作流程,做网站需要注册公司吗?
如何在 Go 中优雅地映射具有动态字段的 JSON 对象到结构体
微信小程序 五星评分(包括半颗星评分)实例代码
Laravel怎么定时执行任务_Laravel任务调度器Schedule配置与Cron设置【教程】
音乐网站服务器如何优化API响应速度?
如何在服务器上三步完成建站并提升流量?


不能加括号以外的任何表达式(如