为何C++20的std::source_location不提供长度以避免性能损耗?
关于C++20 std::source_location的性能疑问
先看这段日志函数代码:
void Log(std::string_view msg, std::source_location const& loc = std::source_location::current()) { // 存在性能损耗! auto const n = std::strlen(loc.file_name()); auto s = ""s; s.resize(msg.size() + n); std::memcpy(&s[0], msg.data(), msg.size()); std::memcpy(&s[msg.size()], loc.file_name(), n); // sendToRemoteMachine(s); }
显然,如果std::source_location::file_name返回std::string_view,就能直接获取字符串长度,避免调用strlen带来的性能损耗。毕竟std::source_location::file_name返回的是编译期生成的只读信息,编译器完全可以将其封装到std::string_view对象中。
那么为什么C++20的std::source_location不直接提供长度信息,或者返回std::string_view呢?
更新
有一篇相关文章《std::source_location 设计缺陷》专门讨论了这一设计的不合理之处。
问题解答
你指出的性能损耗确实存在——每次调用strlen(loc.file_name())都会遍历整个文件名字符串,而文件名作为编译期确定的常量,其长度本可以直接获取。关于标准如此设计的原因,主要有以下几点:
- 兼容性优先:C++标准库设计时会优先考虑与现有代码的兼容。传统的
__FILE__宏返回const char*类型,std::source_location::file_name()沿用这一返回类型,使得依赖__FILE__的旧代码可以平滑迁移到std::source_location,无需修改字符串处理逻辑。 - 标准制定的权衡:虽然从技术实现上,编译器完全可以在编译期计算出文件名长度,并将其存储到
std::source_location对象中(或直接返回std::string_view),但标准委员会可能认为,这一优化带来的收益不足以抵消兼容性成本,或者在提案阶段未充分讨论该方向的优化。 - 实现灵活性:返回
const char*给编译器留下了更多实现空间,比如直接复用现有__FILE__的字符串存储,无需额外维护长度信息,降低了编译器实现的复杂度。
规避性能损耗的方案
如果你想避免strlen的开销,可以自行封装一个工具函数,在编译期将文件名转换为std::string_view:
#include <source_location> #include <string_view> constexpr std::string_view get_file_name(std::source_location const& loc) { return std::string_view(loc.file_name()); }
std::string_view的构造会在编译期自动计算出字符串长度,后续使用时直接调用size()即可,无需再调用strlen。
内容的提问来源于stack exchange,提问作者xmllmx
相关产品推荐
相关产品推荐

