5

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

4

7 回答 7

10

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

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;
于 2009-09-07T14:09:06.623 回答
6

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

只是我的 0.02 美元.....

于 2009-09-07T14:03:06.057 回答
5

用以下内容替换您的调试输出语句:

IFDBG(cout << result << endl);

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

#ifdef DEBUG
#  define IFDBG(x) x
#else
#  define IFDBG(x)
#endif
于 2009-09-07T13:58:27.820 回答
4

如果您正在寻找快速删除调试语句的东西,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;
}

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

于 2009-09-07T15:09:18.437 回答
4

定义这个宏:

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

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

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

于 2015-08-06T21:58:26.103 回答
3

您可能可以使用一个名为 的实例来定义一个新的类流类,cerr但它什么也不做。如果你真的很幸运,编译器会看到该函数什么都不做,并优化对operator<<()out 的调用。

就像是

class NullStream
{
public:
  NullStream();

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

不过,这确实是个技巧,最好通过您的源代码并添加对日志记录的适当支持。

于 2009-09-07T14:01:48.050 回答
0

定义一个替换的宏cout不是你应该上传到你的 VCS 的东西,但是如果你只是在调试期间临时做它,我认为它可以发挥作用。所以你可以coutostream(0)like替换

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

这样,它可以同时使用std::cout和 plain cout,并且ostream在包含 时可用<iostream>。写入 aostream(0)是无操作的。函数调用已完成,以便您获得对它的非常量引用(因此它还绑定到用于输出和其他的flush非成员)。由于它的类型,它的行为应该与.operator<<std::stringostreamcout

于 2009-09-07T23:51:54.750 回答