Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ &引用;空记录器";-使用ostream运算符的空类是否会从优化的代码中编译出来?_C++_Performance - Fatal编程技术网

C++ &引用;空记录器";-使用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 #

如果我有一个日志类,它在发布模式下是空的,并且有一个ostream操作符,它什么都不做。大致上是这样的:

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代码的工作示例。

Are
LOG\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*/