我的大多数类都有调试变量,这使得它们通常如下所示:
class A
{
// stuff
#ifndef NDEBUG
int check = 0;
#endif
};
方法可能如下所示:
for (/* big loop */) {
// code
#ifndef NDEBUG
check += x;
#endif
}
assert(check == 100);
没有什么东西比那些#ifndef NDEBUG更丑了。不幸的是,我知道没有这些#ifndefs,没有编译器能够优化check变量(我不知道这是否被允许)。
所以我试着想出一个能让我的生活更轻松的解决方案。现在的情况如下:
#ifndef NDEBUG
#define DEBUG_VAR(T) T
#else
template <typename T>
struct nullclass {
inline void operator+=(const T&) const {}
inline const nullclass<T>& operator+(const T&) const { return *this; }
// more no-op operators...
};
#define DEBUG_VAR(T) nullclass<T>
#endif
因此,在调试模式下,DEBUG_VAR( T )只生成一个T,否则它只生成一个"null类“而没有操作。我的代码看起来是这样的:
class A {
// stuff
DEBUG_VAR(int) check;
};
然后,我可以使用检查,就好像它是一个正常的变量!太棒了!然而,仍有两个问题我无法解决:
1.它只适用于int、等。
"null类“没有push_back()等。无论如何,大多数调试变量都是ints。
2.“空类”的宽度为1个字符!!
C++中的每个类至少有一个字符宽。因此,即使在发布模式下,使用N个调试vars的类也至少是N个字符太大。这在我看来是无法接受的。这违背了我所追求的零开销原则。
那么,如何解决第二个问题呢?是否有可能在不影响性能的情况下摆脱#ifndef?我接受任何好的解决方案,即使这是你最黑暗的C++魔法或C++0x。
发布于 2011-02-16 13:43:09
不如:
#ifndef NDEBUG
#define DEBUG_VAR(T) static nullclass<T>
#endif
现在,在使用DEBUG_VAR(T)
作为成员的类中没有添加任何额外的存储,但是声明的标识符仍然可以像它是成员一样使用。
发布于 2011-02-16 13:40:20
您无法解决第二个问题,因为c++标准要求类或对象的大小至少为一个字节。
最简单的解决方案是不引入此类黑客,并对代码进行适当的单元测试。
发布于 2011-02-16 13:56:08
在调试模式下声明成员对象静态如何:
#define DEBUG_VAR(T) static nullclass<T>
您必须在某个地方定义每个对象的实例。
(顺便说一句,空类的对象必须占用空间的原因是它们可以有唯一的指针。)
编辑:删除第二个想法-不起作用。
https://stackoverflow.com/questions/5017099
复制相似问题