std::print 不是 C++ 标准库的一部分,截至 C++23 仍未纳入;它仅见于实验性提案或第三方库(如 fmt::print),标准输出仍依赖线程不安全的 std::cout,需结合 fmt 库、std::mutex 和 ANSI 控制序列实现线程安全彩色输出。

std::print 不存在于当前任何正式发布的 C++ 标准(C++20、C++23 均未包含),它不是标准库的一部分。你看到的可能是实验性提案(如 P2093)的早期实现、第三方库(如 fmt 的 fmt::print)、或误传的名称。
为什么 std::print 不能直接用
截至 C++23,标准库中没有 std::print。C++ 的标准输出仍依赖 std::cout / std::ostream,而它们本身不提供线程安全的格式化输出,也不内置 ANSI 彩色控制序列支持。
-
std::cout <<操作在多线程下非原子——多个线程同时写入可能产生字符交错(如 “He[red]ll[reset]o” 变成 “Hel[red]lo[reset]”) - ANSI 转义序列(如
"\x1b[31m")需手动拼接,易出错且难以维护 - 即使某些编译器(如 MSVC 预览版)实验性支持
std::print,也未保证线程安全或彩色能力
替代方案:用 fmt::print + std::mutex 实现线程安全彩色输出
最接近需求的成熟方案是 fmt 库(fmt::print 是其核心函数),它支持格式化、ANSI 彩色,并可通过简单加锁实现线程安全。
- 安装:
git clone https://github.com/fmtlib/fmt或通过 vcpkg/conan 获取 - 启用彩色需传入 ANSI 转义序列,例如
"{0}\x1b[0m"(重置)或"\x1b[32m{0}\x1b[0m"(绿色) - 线程安全靠外部互斥量保护:每次调用
fmt::print前 lock,结束后 unlock - 不要用
std::osyncstream(C++20)——它只保证单次<<不被拆开,不解决跨调用的交错,也不支持彩色格式化
示例:
立即学习“C++免费学习笔记(深入)”;
std::mutex print_mutex;
void safe_print_color(const char* color, const char* msg) {
std::lock_guard<std::mutex> lk(print_mutex);
fmt::print("{}{}{}\n", color, msg, "\x1b[0m");
}
// 使用:safe_print_color("\x1b[31m", "Error occurred");更实用的做法:封装一个带颜色和锁的日志函数
硬编码转义序列容易出错,建议把颜色抽象为枚举或常量,并统一管理锁与换行。
- 定义颜色宏:
inline constexpr auto RED = "\x1b[31m"; inline constexpr auto GREEN = "\x1b[32m"; - 避免在格式字符串里重复写
\x1b[0m,改为函数内自动追加 - 若性能敏感,可考虑
std::stringstream先构造完整字符串再一次性输出,减少锁持有时间 - Windows 控制台需先启用 ANSI 支持(
SetConsoleOutputCP(CP_UTF8)和SetConsoleMode启用ENABLE_VIRTUAL_TERMINAL_PROCESSING)
真正要“线程安全 + 彩色 + 控制台输出”,靠标准库原生功能做不到。必须组合外部库(fmt)+ 显式同步(std::mutex)+ 平台适配(Windows ANSI 开关)。漏掉任意一环,要么没颜色,要么输出乱码,要么依然线程不安全。


















