如何实现仅可单次初始化、支持默认级别的C++无框架简易日志
解决方案:利用
std::call_once保证日志级别仅初始化一次 最直接且线程安全的实现方式是使用C++标准库的std::once_flag和std::call_once,它们可以确保日志级别初始化逻辑仅执行一次,完全满足你"一次性初始化、后续不可修改"的需求,同时无需引入单例模式的复杂度。
代码修改方案
1. 更新logging.cpp
#include "logging.h" #include <mutex> // 引入std::once_flag和std::call_once #include <cassert> // 可选:用于调试模式下的重复初始化断言 static std::once_flag s_init_flag; static LogLevel s_log_level = NoLog; // 默认日志级别 void initLogger(LogLevel level) { bool is_first_init = false; // 确保初始化逻辑仅执行一次 std::call_once(s_init_flag, [&]() { s_log_level = level; is_first_init = true; }); // 可选:调试模式下,若重复调用则触发断言提示 assert(is_first_init && "initLogger 不可重复调用"); } LogLevel loggerLevel() { return s_log_level; }
2. 原头文件logging.h无需修改
头文件中的枚举、宏定义和函数声明保持原样即可。
效果说明
- 用户首次调用
initLogger时,日志级别会被设置为指定值,后续无论多少次调用initLogger,日志级别都不会再改变。 - 若用户未调用
initLogger,则默认使用NoLog级别,符合你"跳过初始化直接用默认值"的需求。 std::call_once是线程安全的,即使在多线程环境下同时调用initLogger,也能保证日志级别仅被初始化一次,避免竞态条件。
额外优化建议
如果希望在release模式下也能对重复初始化做提示,可以将断言替换为自定义的日志输出(注意避免递归日志调用),比如:
#include <iostream> void initLogger(LogLevel level) { bool is_first_init = false; std::call_once(s_init_flag, [&]() { s_log_level = level; is_first_init = true; }); if (!is_first_init) { std::cerr << "警告:initLogger 已被初始化,重复调用无效" << std::endl; } }
内容的提问来源于stack exchange,提问作者vazlsky
相关产品推荐
相关产品推荐

