5

我有一个非常基本的类,将其命名为 Basic,几乎用于一个更大项目的所有其他文件。在某些情况下,需要有调试输出,但在发布模式下,这不应该被启用并且是 NOOP。

目前在标题中有一个定义,它根据设置打开或关闭 makro。因此,当关闭时,这绝对是一个 NOOP。我想知道,如果我有以下代码,编译器(MSVS / gcc)是否能够优化函数调用,使其再次成为 NOOP。(通过这样做,开关可以在 .cpp 中,并且切换会更快,编译/链接时间明智)。

--Header--
void printDebug(const Basic* p);

class Basic {
   Basic() {
      simpleSetupCode;

      // this should be a NOOP in release, 
      // but constructor could be inlined
      printDebug(this);
   }
};
--Source--
// PRINT_DEBUG defined somewhere else or here
#if PRINT_DEBUG
void printDebug(const Basic* p) {
   // Lengthy debug print
}
#else
void printDebug(const Basic* p) {}
#endif
4

5 回答 5

1

与所有此类问题一样,答案是 - 如果它对您真的很重要,请尝试该方法并检查发出的汇编语言。

于 2010-05-04T08:35:53.277 回答
1

如果编译器在编译时知道 printDebug 函数的实现,则编译器可能会优化此代码。如果 printDebug 在另一个目标模块中,这可能仅由链接器优化,使用整个程序优化。但测试这一点的唯一方法是阅读编译器生成的汇编代码。如果你已经有了 PRINT_DEBUG 宏,你可以按照 TRACE 定义的方式来扩展它:

#define PRINT_DEBUG // 可选
#ifdef PRINT_DEBUG
#define PRINT_DEBUG_CALL(p) printDebug(p)
#别的
#define PRINT_DEBUG_CALL(p)
#万一


无效 printDebug(const Basic* p);

类基本{
   基本的() {
      简单设置代码;

      // 这应该是发布中的 NOOP,
      // 但是构造函数可以被内联
      PRINT_DEBUG_CALL(这个);
   }
};
- 资源 - 
// PRINT_DEBUG 定义在别处或这里
#if PRINT_DEBUG
无效打印调试(常量基本* p){
   // 冗长的调试打印
}
#万一
于 2010-05-04T08:42:11.440 回答
1
#if PRINT_DEBUG
#define printDebug _real_print_debug
#else
#define printDebug(...)
#endif

这样,预处理器甚至会在进入编译器之前剥离所有调试代码。

于 2010-05-04T09:48:46.177 回答
1

目前大多数优化都是在编译时完成的。LLVM等一些编译器能够在链接时进行优化。这是一个非常有趣的想法。我建议你看看。

等待这些优化,你可以做的是以下。根据是否定义 DEBUG 定义一个宏,让您包含以下语句。

#ifdef DEBUG
#define IF_DEBUG (false) {} else
#else
#define IF_DEBUG 
#endif

你可以像这样使用它

   Basic() {
      simpleSetupCode;

      // this should be a NOOP in release, 
      // but constructor could be inlined
      IF_DEBUG printDebug(this);
   }

这已经比

   Basic() {
      simpleSetupCode;

      // this should be a NOOP in release, 
      // but constructor could be inlined
#if DEBUG
      printDebug(this);
#endif
   }

请注意,您可以像使用关键字一样使用它

IF_DEBUG {
   printDebug(this);
   printDebug(thas);
}
于 2010-05-04T09:15:24.073 回答
0

errm,为什么不以不同的方式使用预处理器宏?

就在我的头顶,类似:

  #define DEBUG_TRACE(p)
  #ifdef PRINT_DEBUG
    printDebug(p);
  #else
    ;
  #endif
于 2010-05-04T08:48:05.347 回答