使用预处理器取消std :: cout代码行

时间:2009-09-07 13:54:56

标签: c++ c-preprocessor cout

可以使用printf()删除对#define printf的所有来电。如果我有很多调试打印如std::cout << x << endl;怎么办?如何使用预处理器在单个文件中快速关闭cout <<语句?

7 个答案:

答案 0 :(得分:9)

正如“放松”已经说过,快速解决方案是无所事事的流。但是有更好的实现:

class NullStream {
    public:
    NullStream() { }
    template<typename T> NullStream& operator<<(T const&) { return *this; }
};

std::cout仍然存在轻微问题,因为这是一个包含三个令牌的序列,您实际上并不想单独重新定义stdcout。一个简单的解决方案是

#ifdef NDEBUG
    #define COUT std::cout
#else
    #define COUT NullStream()
#endif

COUT << "Hello, world" << std::endl;

答案 1 :(得分:6)

作为一般原则,应该避免记录到stdout - 更好地记录到日志文件,然后您可以使用标准配置工具来更改日志级别,或者完全关闭它。

只需我0.02美元.....

答案 2 :(得分:3)

用这样的代码替换你的调试输出语句:

IFDBG(cout << result << endl);

然后您可以相应地定义宏:

#ifdef DEBUG
#  define IFDBG(x) x
#else
#  define IFDBG(x)
#endif

答案 3 :(得分:3)

您可以执行一个预处理程序hack,它定义一个新的类类,使用名为cerr的实例,它什么都不做。如果你真的很幸运,编译器会看到该函数什么也不做,并优化了对operator<<()的调用。

这样的东西
class NullStream
{
public:
  NullStream();

  NullStream& operator<<(const std::string& text) { return *this; }
  // And operators for other types, too
}
static NullStream cerr;

这是非常糟糕的,但通过源代码并添加适当的日志记录支持(远)更好。

答案 4 :(得分:3)

如果您正在寻找快速删除调试语句的东西,NullStream可以是一个很好的解决方案。但是我建议创建自己的调试类,当需要更多调试功能时,可以根据需要进行扩展:

class MyDebug
{
    std::ostream & stream;
  public:
    MyDebug(std::ostream & s) : stream(s) {}
#ifdef NDEBUG
    template<typename T>
    MyDebug & operator<<(T& item)
    {
      stream << item;
      return *this;
    }
#else
    template<typename T>
    MyDebug & operator<<(T&)
    {
      return *this;
    }
#endif
};

这是一个简单的设置,可以做你想要的最初,另外它还有一个额外的好处,你可以添加调试级别等功能。

<强>更新 现在,由于操纵器是作为函数实现的,如果你也想接受操纵器(endl),你可以添加:

MyDebug & operator<<(std::ostream & (*pf)(std::ostream&))
{
  stream << pf;
  return *this;
}

对于所有操纵器类型(因此您不必为所有操纵器类型重载):

template<typename R, typename P>
MyDebug & operator<<(R & (*pf)(P &))
{
  stream << pf;
  return *this;
}

小心这最后一个,因为它也会接受常规函数指针。

答案 5 :(得分:3)

定义此宏:

#ifdef DEBUG
    #define MY_LOG std::cout
#else
    #define MY_LOG if(false) std::cout
#endif

这个宏优势在于编译器优化

  

如果置于这些IF中的表达式在编译时是常量且可确定的,那么您几乎可以确定编译器已经将它们从代码中删除了...   https://stackoverflow.com/a/14657645/5052296

答案 6 :(得分:0)

定义一个替换cout的宏不是你应该上传到你的VCS的东西,但如果你只是在调试期间暂时这样做,我认为它适用于它的位置。因此,您只需将cout替换为ostream(0),如

#ifdef NDEBUG
#define cout ostream(0).flush()
#endif

这样,它适用于std::cout和普通coutostream可用<iostream>。写入ostream(0)是一种无操作。完成flush函数调用,以便获得对它的非const引用(因此它也绑定到用于输出operator<<和其他人的非成员std::string)。由于其类型为ostream,因此其行为应与cout完全相同。