std::format需包含头文件并启用c++20标准(gcc 13+/clang 15+/msvc 19.30+),格式串必须为字面量,不支持运行时拼接、自定义格式器或%语法,性能高效但需手动特化std::formatter以支持自定义类型。

std::format 在 C++20 中可用,但必须启用 C++20 标准且编译器支持(GCC 13+、Clang 15+、MSVC 19.30+),否则会报 std::format 未声明的错误。
如何正确包含和启用 std::format
它不属于 <iostream></iostream> 或 <string></string>,必须显式包含 <format></format>。同时需确认编译器标志已设为 C++20:
- GCC/Clang:加
-std=c++20(-std=gnu++20也可) - MSVC:用
/std:c++20 - 注意:GCC 12 默认不启用
std::format,即使加了-std=c++20,还需链接-lstdc++并确保 libstdc++ 版本 ≥ 13
基本格式化写法与常见占位符
std::format 接收格式字符串和参数,返回 std::string;不支持运行时拼接格式串(即格式串必须是字面量或 consteval 表达式):
std::string s = std::format("Hello, {}!", "World"); // OK
int x = 42;
auto s2 = std::format("Value: {:d}", x); // {:d} 强制十进制,等价于 {}
auto s3 = std::format("{:.2f}", 3.14159); // 输出 "3.14"
auto s4 = std::format("{:08x}", 255); // 输出 "000000ff"
- 类型推导默认足够智能,多数场景直接用
{}即可 - 整数默认按有符号输出,
{:x}、{:X}、{:b}分别为小写十六进制、大写十六进制、二进制 - 浮点数默认六位有效数字,
{:.Nf}控制小数位数,{:e}切换科学计数法 - 字符串不支持宽度填充对齐以外的修饰(如无
{:s}这种冗余说明符)
std::format 不支持哪些常见操作
它不是 printf 的翻版,设计上更安全、更受限:
立即学习“C++免费学习笔记(深入)”;
- ❌ 不支持变参函数式调用(不能写
std::format(fmt, a, b, c)且fmt是运行时std::string)——编译期校验要求格式串为字面量 - ❌ 不支持自定义格式化器(除非特化
std::formatter模板,且该类型需满足formattable要求) - ❌ 不支持字段宽度或精度由参数传入(如
{:* 非法;宽度必须是字面量或 <code>arg-id,如{:*>5}或{:>{}}配合额外参数) - ❌ 不支持
%风格语法(%d、%s等全部无效)
性能与替代方案权衡
std::format 是零开销抽象的典型:编译期解析格式串,生成高效代码;但首次调用可能触发静态初始化开销。若你频繁格式化同一模式(如日志前缀),可预编译为 std::basic_format_string:
static constexpr auto log_fmt = std::format_string("[{:3d}] {}");
std::string msg = std::format(log_fmt, line_num, text);
- 比每次构造
"[{:3d}] {}"字面量略快(避免重复解析) - 但仅当格式串确定且复用频繁时才值得——多数场景直接用字面量即可
- 若目标平台不支持 C++20 或标准库未就绪,
absl::StrFormat(Abseil)、fmt::format({fmt} 库)是更成熟、兼容性更好的替代
最常被忽略的一点:std::format 对用户自定义类型的格式化不是开箱即用的,必须显式提供 std::formatter 特化,并确保该特化满足 consteval 友好性和 SFINAE 友好性——否则编译失败信息往往晦涩难懂。










