C++ &引用;空记录器";-使用ostream运算符的空类是否会从优化的代码中编译出来?
如果我有一个日志类,它在发布模式下是空的,并且有一个ostream操作符,它什么都不做。大致上是这样的:C++ &引用;空记录器";-使用ostream运算符的空类是否会从优化的代码中编译出来?,c++,performance,C++,Performance,如果我有一个日志类,它在发布模式下是空的,并且有一个ostream操作符,它什么都不做。大致上是这样的: struct null_logger { template<typename T> inline null_logger& operator<<(T) { return *this; } }; 这不是对您问题的直接回答,但通常您会以另一种方式禁用日志记录:您只是不通过短路来评估LOG\u DBG之后的内容,这相当简单: #ifdef NDEBUG #
struct null_logger
{
template<typename T> inline null_logger& operator<<(T) { return *this; }
};
这不是对您问题的直接回答,但通常您会以另一种方式禁用日志记录:您只是不通过短路来评估
LOG\u DBG
之后的内容,这相当简单:
#ifdef NDEBUG
#define LOG_CHECK false &&
#elseif
#define LOG_CHECK /*empty*/
#define LOG_DBG LOG_CHECK /*your_debug_logging_code*/
这样,您就可以保证LOG_DBG之后的所有内容都是死代码,可以在发布模式下进行优化
注意,即使没有编译出来,由于短路,它们也不会在运行时执行
现在,为了让它真正起作用,/*您的调试日志记录\u code*/
需要计算为布尔值,例如通过safe bool习惯用法。例如,IOstreams会这样做,让您知道流的状态是否仍然正常
class Logger{
typedef void (Logger::*safe_bool)();
void safe_bool_check(){}
public:
// ...
operator safe_bool() const{
return check_state() ? &Logger::safe_bool_check : 0;
}
};
当然,如果您只希望布尔转换使短路工作,您可以简单地返回0转换运算符中的代码>
请注意,如果您使用的是真正最新版本的GCC或Clang,您可能已经有权访问显式
转换运算符:
另一种方法可能是使用三元运算符进行短路。但是,两个“分支”必须是相同的类型,因此我们将在这里使用一个小技巧,一个可以从任何内容构造的简单类:
namespace log_detail{
struct log_check_helper{
log_check_helper(){}
template<class T>
log_check_helper(T const&){}
};
}
#ifdef NDEBUG
#define LOG_CHECK true ? log_detail::log_check_helper() :
#else
#define LOG_CHECK /*empty*/
#endif
#define LOG_DBG LOG_CHECK /*your_debug_logging_code*/
名称空间日志\u详细信息{
结构日志检查辅助程序{
日志检查帮助程序(){}
模板
日志检查辅助程序(T常量&){
};
}
#ifdef-NDEBUG
#定义日志检查是否为真?log\u detail::log\u check\u helper():
#否则
#定义日志检查/*空*/
#恩迪夫
#定义LOG\u DBG LOG\u CHECK/*调试日志记录代码*/
使用一个编译而不计算IOstream代码的工作示例。AreLOG\u DBG为什么不检查生成的汇编代码,这将是最好的确认。通常,如果不使用,编译器将优化创建变量等,但在这种情况下,这有点难说,因为@JesseGood您是对的,这不是一个完整的列表-在调试模式下,LOG_DBG宏将扩展为完整的日志实现。我道歉,我认为这会混淆我的意图question@Als,我担心我缺乏汇编方面的知识,这就是为什么我求助于StackOverflow的集体知识。您只需制作一个简单的代码示例,编译它,生成汇编,并检查类似于调用之类的指令,如果您不能理解生成的程序集输出,您可以将其与代码示例一起发布到Q中,这样您将得到比猜测更多的结论性答案。我尝试实现了这一点,并在发布模式下得到以下结果:与false&&Logger中的“operator&&”不匹配::operator@lori:哎呀,我的错。您需要将记录器
转换为布尔类型(例如,通过safe-bool习惯用法),或者稍微迂回一点。我会在中编辑的。我明白了-太好了,谢谢!被接受为答案,因为它实现了我的目标
class Logger{
typedef void (Logger::*safe_bool)();
void safe_bool_check(){}
public:
// ...
operator safe_bool() const{
return check_state() ? &Logger::safe_bool_check : 0;
}
};
explicit operator bool() const{ return check_state(); }
namespace log_detail{
struct log_check_helper{
log_check_helper(){}
template<class T>
log_check_helper(T const&){}
};
}
#ifdef NDEBUG
#define LOG_CHECK true ? log_detail::log_check_helper() :
#else
#define LOG_CHECK /*empty*/
#endif
#define LOG_DBG LOG_CHECK /*your_debug_logging_code*/