
在 C++20 中,std::format 是一个全新的文本格式化工具,它借鉴了 Python 的 str.format() 和 Rust 的 format! 语法,提供了类型安全、高性能且易于使用的字符串格式化方式。相比传统的 printf 或 ostringstream,std::format 更加现代、安全且功能强大。
包含头文件与启用 C++20
要使用 std::format,你需要确保编译器支持 C++20,并包含 头文件:
#include#include int main() { std::string message = std::format("Hello, {}!", "World"); std::cout << message << '\n'; return 0; }
编译时需启用 C++20:
g++ -std=c++20 -o test test.cpp基本用法:替换占位符
std::format 使用大括号 {} 作为占位符,按顺序填充参数:
立即学习“C++免费学习笔记(深入)”;
std::format("Welcome, {}! You are {} years old.", "Alice", 25);
// 输出: Welcome, Alice! You are 25 years old.
也可以通过索引指定参数顺序:
std::format("{1} is {0} years old.", 30, "Bob");
// 输出: Bob is 30 years old.
还可以使用命名参数(虽然目前标准库不直接支持运行时命名,但可通过结构体或自定义类型模拟)。
格式化数字与控制精度
可以像 printf 一样控制整数进制、浮点数精度等:
-
十六进制:
{:x}或{:X} -
八进制:
{:o} -
二进制:
{:b} -
浮点数精度:
{:.2f}
std::format("Hex: {:x}, Octal: {:o}, Binary: {:b}", 255, 255, 255);
// 输出: Hex: ff, Octal: 377, Binary: 11111111
std::format("Pi is {:.2f}", 3.1415926);
// 输出: Pi is 3.14
支持对齐和填充:
std::format("{:>10}", "right"); // 右对齐,宽度10
// 输出: " right"
std::format("{:-<10}", "left"); // 左对齐,用'-'填充
// 输出: "left------"
格式化时间(C++20 chrono 支持)
std::format 原生支持 std::chrono 类型,可轻松格式化时间:
#includeauto now = std::chrono::system_clock::now(); std::string timestr = std::format("{:%Y-%m-%d %H:%M:%S}", now); // 输出类似: 2025-04-05 14:30:22
常用时间格式符:
-
%Y: 四位年份 -
%m: 月份(01-12) -
%d: 日期 -
%H: 小时(24小时制) -
%M: 分钟 -
%S: 秒
自定义类型格式化
要让自定义类型支持 std::format,需要特化 std::formatter 模板:
struct Point {
int x, y;
};
template<>
struct std::formatter {
constexpr auto parse(auto& ctx) {
return ctx.begin();
}
auto format(const Point& p, auto& ctx) const {
return std::format_to(ctx.out(), "({},{})", p.x, p.y);
}
};
// 使用
std::format("Point is {}", Point{1, 2});
// 输出: Point is (1,2)
这个过程需要熟悉 parse 和 format 两个阶段:parse 解析格式选项,format 实际写入输出迭代器。
常见问题与注意事项
- MSVC 对
支持较好,GCC 需要较新版本(如 GCC 13+),Clang 支持逐步完善。 - 某些标准库实现可能默认未启用
,需检查编译器文档。 - 性能上,std::format 通常优于
ostringstream,接近优化后的printf。 - 不支持运行时命名参数(如
{name}),但可通过索引复用参数:{0} {0}。











