可以使用printf()
删除对#define printf
的所有来电。如果我有很多调试打印如std::cout << x << endl;
怎么办?如何使用预处理器在单个文件中快速关闭cout <<
语句?
答案 0 :(得分:9)
正如“放松”已经说过,快速解决方案是无所事事的流。但是有更好的实现:
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;
答案 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
和普通cout
,ostream
可用<iostream>
。写入ostream(0)
是一种无操作。完成flush
函数调用,以便获得对它的非const引用(因此它也绑定到用于输出operator<<
和其他人的非成员std::string
)。由于其类型为ostream
,因此其行为应与cout
完全相同。