查看两个宏的代码会发现差异:
qDebug():
#define qDebug QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).debug
qCDebug():
# define qCDebug(category, ...) \
for (bool qt_category_enabled = category().isDebugEnabled(); qt_category_enabled; qt_category_enabled = false) \
QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, category().categoryName()).debug(__VA_ARGS__)
所以主要区别在于,qCDebug(cat) 将检查类别是否已启用,在创建 QMessageLogger 实例之前。如果我们使用qDebug() 宏,存在一个带有 QLoggingCategory 参数的重载函数,我想是为了方便起见?这个函数will perform the check只有在QMessageLogger被创建之后。
我设置了一个简单的基准来查看它所带来的性能差异 - 代码如下。保持所有测试的消息长度相同,我得到了以下结果(括号中的数字表示迭代次数,值是每次迭代的平均时间,以毫秒为单位):
+----------+---------------+-------------------+--------+
| category | qDebug | qCDebug | Factor |
+----------+---------------+-------------------+--------+
| enabled | 0.031(2048) | 0.024(4096) | 1.29 |
| disabled | 0.00077(4096) | 0.000016(4194304) | 48.0 |
+----------+---------------+-------------------+--------+
当然,确切的数字各不相同,但整体形象保持不变。如果启用该类别的调试输出,则两个宏的执行大致相同,而如果禁用该类别,使用qCDebug 将比qDebug 快大约十到一百倍。因此,正如文档所建议的那样,在处理类别时,应该始终使用 qCDebug,尽管只有在生成 lot 的(禁用)输出时,差异才可能会很明显。
下面的验证测试代码:
Q_LOGGING_CATEGORY(test, "test")
class DebugBM: public QObject
{
Q_OBJECT
private slots:
void xdebugEnabled()
{
QBENCHMARK {
qDebug(test) << "Test.";
}
}
void cDebugEnabled()
{
QBENCHMARK {
qCDebug(test) << "Test.";
}
}
void xdebugDisable()
{
QLoggingCategory::setFilterRules("test.debug=false");
QBENCHMARK {
qDebug(test) << "Test.";
}
}
void cDebugDisable()
{
QLoggingCategory::setFilterRules("test.debug=false");
QBENCHMARK {
qCDebug(test) << "Test.";
}
}
};
QTEST_MAIN(DebugBM)
#include "DebugBM.moc"