C++ 调用空类方法是否会影响性能?

C++ 调用空类方法是否会影响性能?,c++,performance,visual-studio-2005,C++,Performance,Visual Studio 2005,计时器.h: class Timer { public: void start(); void printTimeAndRestart(const char* msg); }; namespace Timing { static Timer timer; } class Timer { public: void start(); void printTimeAndRestart(const char* msg); }; namespace Timing { stati

计时器.h:

class Timer
{
public:
void start();
void printTimeAndRestart(const char* msg);
};
namespace Timing {    static Timer timer; }
class Timer
{
  public:
  void start();
  void printTimeAndRestart(const char* msg);
};

namespace Timing {    static Timer timer; }

#ifndef DO_TIMING
inline void Timer::start() {}
inline void printTimeAndRestart(const char*) {}
#endif
Timer.cpp:

#ifdef DO_TIMING
//implementation
void Timer::start() { ... };
void Timer::printTimeAndRestart(const char* msg) { ... };
#else
//empty - do not do timing
void Timer::start() {};
void Timer::printTimeAndRestart(const char* /*msg*/) {};
#endif
#ifdef DO_TIMING
//implementation
void Timer::start() { ... };
void Timer::printTimeAndRestart(const char* msg) { ... };
#endif
计时器将用于许多不同的文件,如:

Timing::timer.start(); 
... 
Timing::timer.printTimeAndRestart("Operation X took :");
若应用程序对性能非常敏感,并且经常调用计时器,那个么在并没有定义时间的情况下调用空方法会影响性能吗?实现独立计时器(无需重新编译整个项目来打开/关闭)的更好选项是什么?关闭时,它根本不会影响性能

到目前为止,我只想到定义宏,比如

#ifdef DO_TIMING 
#define START_TIMING()
Timing::timer.start(); 
#endif
#else
#define START_TIMING()
#endif

并使用它们而不是计时::timer.start();但这将需要重新编译整个代码来打开/关闭它们…

在调试构建中,这将被调用,并将具有任何函数调用的总体效果。在优化代码中,编译器通常会忽略调用

根据下面的评论


在调用站点,编译器将无法确定被调用函数是否无效。如果宏也内联定义了空条件,那么调用站点将能够看到函数本质上是一个noop。

这取决于您如何使用它。如果它是同一个项目/解决方案,并且编译器能够进行完整的程序优化,那么它可能与此无关


如果您正在分发带有二进制文件的代码,并且实现不可见,并且编译器无法判断代码是否为空,则调用将产生一些(较小的)开销。

如果您希望编译器更确定地优化调用,请执行以下操作:

计时器.h:

class Timer
{
public:
void start();
void printTimeAndRestart(const char* msg);
};
namespace Timing {    static Timer timer; }
class Timer
{
  public:
  void start();
  void printTimeAndRestart(const char* msg);
};

namespace Timing {    static Timer timer; }

#ifndef DO_TIMING
inline void Timer::start() {}
inline void printTimeAndRestart(const char*) {}
#endif
Timer.cpp:

#ifdef DO_TIMING
//implementation
void Timer::start() { ... };
void Timer::printTimeAndRestart(const char* msg) { ... };
#else
//empty - do not do timing
void Timer::start() {};
void Timer::printTimeAndRestart(const char* /*msg*/) {};
#endif
#ifdef DO_TIMING
//implementation
void Timer::start() { ... };
void Timer::printTimeAndRestart(const char* msg) { ... };
#endif

高质量的编译器可能会将其删除,但更安全的做法是确保空函数内联在.h文件中:

定时器

class Timer
{
public:
  void start();
  void printTimeAndRestart(const char* msg);
};

#ifndef DO_TIMING

inline void Timer::start() {}
inline void printTimeAndRestart(const char* msg) {}

#endif

namespace Timing {    static Timer timer; }
Timer.cpp

#ifdef DO_TIMING

// ...

#endif

不幸的是,这确实意味着您将依赖项绑定到头文件中,这将导致在打开或关闭时重新编译。

如果函数定义为“内联”(即,作为声明它们所属类的头文件的一部分),则编译器可以避免为空函数生成代码。如果函数位于.cpp文件中,编译器必须生成调用函数的代码,因为编译器无法知道函数的功能[除非编译器支持“全程序优化”]


我的解决方案是将函数移到头文件中,而不是使用宏。这是一个更简洁的解决方案,除非编译器完全是垃圾,否则它应该把它归类为“没有生成代码”

编译器如何能够省略调用?定义不在同一个TU中,我不会假设LTO。它可以确定任何空函数都没有效果,因此不调用它。这类似于编译器在优化时如何将函数优化为内联。但在编译调用所在的文件时,它无法知道函数没有任何效果,因为它看不到其定义或任何东西。这一点很好。整个程序优化将能够实现。或配置文件引导。但更好的是,它应该是内联定义的,而不是没有效果。还没有-在上面所写的实现过程中,但我发布了一些帖子,看看还有哪些其他设计选项/是否有可能通过查看desingYep立即判断性能是否会受到影响…这将增加更多确定性(对于确定性的某些定义). 尽管当在代码库中任意添加一个
#define
可能会破坏这样的东西时,我会感到不安。(无可否认,提问者发明了
#define