printf()
可以删除所有对using的调用#define printf
。如果我有很多类似的调试打印std::cout << x << endl;
怎么办?如何cout <<
使用预处理器快速关闭单个文件中的语句?
7 回答
正如“放松”已经说过的那样,快速解决方案是无所事事的流。虽然有更好的实现:
class NullStream {
public:
NullStream() { }
template<typename T> NullStream& operator<<(T const&) { return *this; }
};
您仍然有一个小问题,std::cout
因为这是三个标记的序列,您真的不想重新定义std
或cout
单独定义。一个简单的解决方案是
#ifdef NDEBUG
#define COUT std::cout
#else
#define COUT NullStream()
#endif
COUT << "Hello, world" << std::endl;
作为一般原则,应避免记录到标准输出 - 最好记录到日志文件,然后您可以使用标准配置工具更改日志级别,或完全关闭它。
只是我的 0.02 美元.....
用以下内容替换您的调试输出语句:
IFDBG(cout << result << endl);
然后您可以相应地定义宏:
#ifdef DEBUG
# define IFDBG(x) x
#else
# define IFDBG(x)
#endif
如果您正在寻找快速删除调试语句的东西,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;
}
最后一个要小心,因为它也会接受常规函数指针。
定义这个宏:
#ifdef DEBUG
#define MY_LOG std::cout
#else
#define MY_LOG if(false) std::cout
#endif
这个宏优势在于编译器优化
如果放置在这些 IF 中的表达式在编译时是常量且可确定的,那么您几乎可以肯定编译器已经为您从代码中删除了它们... https://stackoverflow.com/a/14657645/5052296
您可能可以使用一个名为 的实例来定义一个新的类流类,cerr
但它什么也不做。如果你真的很幸运,编译器会看到该函数什么都不做,并优化对operator<<()
out 的调用。
就像是
class NullStream
{
public:
NullStream();
NullStream& operator<<(const std::string& text) { return *this; }
// And operators for other types, too
}
static NullStream cerr;
不过,这确实是个技巧,最好通过您的源代码并添加对日志记录的适当支持。
定义一个替换的宏cout
不是你应该上传到你的 VCS 的东西,但是如果你只是在调试期间临时做它,我认为它可以发挥作用。所以你可以cout
用ostream(0)
like替换
#ifdef NDEBUG
#define cout ostream(0).flush()
#endif
这样,它可以同时使用std::cout
和 plain cout
,并且ostream
在包含 时可用<iostream>
。写入 aostream(0)
是无操作的。函数调用已完成,以便您获得对它的非常量引用(因此它还绑定到用于输出和其他的flush
非成员)。由于它的类型,它的行为应该与.operator<<
std::string
ostream
cout