c++ - 用空实现替换“定义宏”
问题描述
我通常使用#define
宏来添加代码,这些代码将在编译为调试时而不是在编译为发布时出现。例如:
#ifdef NDEBUG
# define LOG(msg) (void)msg
#else
# define LOG(msg) MyDebugLogger(msg)
#endif
取而代之的是,我正在考虑使用普通函数,只是不为 release 方法提供主体:
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 中增加额外的成本。我对么?出于某种原因,这可能是一种不好的做法吗?
编辑:我的问题是:如果我像以前一样使用宏,我知道在发布模式下,可执行文件会更小更快,因为所有代码都已被删除。如果我使用该功能,它会一样吗?正如编译器可能理解的那样,该函数什么都不做,也没有必要。(或者它会增加一个额外的,甚至很小的,用于调用一个空函数)
解决方案
你的例子应该可以工作,稍微调整一下。在您当前的版本中,编译器仅“看到”函数签名并将发出对其符号的调用,该符号稍后将通过链接器解决,因此它无法自行优化它。(链接时间优化可能对此有所帮助,但这在很大程度上取决于您的设置,而动态链接将使这成为不可能)。所以也许在标题中尝试这样的事情:
// 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 编译 Logger,而此方法为客户端代码提供了选择。
推荐阅读
- typescript - 如何使用 TypeScript 重用类构造函数参数作为文字字符串?
- python - 基本 Python 练习:给定一个整数列表,如果有重复,则放置一个“*”
- javascript - 循环遍历单个元素 - Laravel
- python-3.x - Keras中的卷积自动编码器解码器错误
- java - 为什么这个函数调用中有 NullPointerException?
- pandas - 如何在 csv 文件中添加分隔符
- go - 我使用 goroutine 进行 parral 的内存激增,最终 oom
- android - Android LiveData 以陈旧的发射触发。. . 只有某些时候 。. . 房间数据库更新后
- python-3.x - 如何使用 ezdxf 返回“MTEXT”中的字符串?
- python - 字典作为类中的局部变量