将"定义宏"替换为空实现

Replace 'Define macro' with empty implementation

本文关键字:实现 定义 替换      更新时间:2023-10-16

我通常使用 #define 宏来添加代码,这些代码将在编译为调试时而不是在编译为发布时出现在这里。例如:

#ifdef NDEBUG
# define LOG(msg) (void)msg
#else
# define LOG(msg) MyDebugLogger(msg)
#endif

取而代之的是,我正在考虑使用普通函数,只是没有为发布方法提供正文:

void MyDebugLogger(std::string const& msg);

在 MyDebugLogger 中.cpp:

void MyDebugLogger(std::string const& msg)
{
#ifdef NDEBUG
    std::clog << msg << "n"; // Or whatever
#else
    (void)msg;
#endif
}

我希望编译器将有能力去除调用并在 Release 中不增加额外的成本。我说的对吗?出于某种原因,这可能是一种不好的做法吗?

编辑:我的问题是:如果我像以前一样使用宏,我知道在发布模式下,可执行文件会更小更快,因为所有代码都已删除。如果我使用该功能,它会是一样的吗?因为编译器可能理解该函数不执行任何操作,也不是必需的。(或者它会添加一个额外的,甚至是小的,用于调用空函数)

实际上你会做与宏相同的操作:

void MyDebugLogger(std::string const& msg)
{
#ifdef NDEBUG
    std::clog << msg << "n"; // Or whatever
#endif
}

你的示例应该可以工作,但稍作调整。在当前版本中,编译器只"看到"函数签名,并将发出对其符号的调用,稍后将通过链接器解析,因此它无法自行优化它。(链接时间优化可能会对此有所帮助,但这在很大程度上取决于您的设置,动态链接将使这变得不可能)。所以也许尝试这样的事情在标题中:

// Assuming you are using clang or gcc,
// but is required to not give an error by the standard and probably
// not even needed.
[[gnu::always_inline]] 
void MyDebugLogger(std::string const& msg [[maybe_unused]])
{
  #ifdef NDEBUG
    MyDebugLoggerImplementation(msg);
  #endif
}

然后在.cpp文件中实现它。这种方法的另一个好处是你方法需要使用 NDEBUG 编译记录器,而此方法为客户端代码提供了选择。