【问题标题】:Why would I prefer qCDebug over qDebug?为什么我更喜欢 qCDebug 而不是 qDebug?
【发布时间】:2020-07-01 13:41:10
【问题描述】:

在 Qt 中,我们可以使用 qDebug - 和类似的 - 宏来进行日志记录。为了组织输出,我们可以定义和使用 QLoggingCategories 以及 qCDebug 宏。

documentation 告诉我们:

宏扩展为检查 QLoggingCategory::isDebugEnabled() 计算结果是否为真的代码。如果是这样,则处理流参数并将其发送到消息句柄

我们通过使用Q_LOGGING_CATEGORY 的类别来做到这一点。考虑以下最小示例:

#include <QCoreApplication>
#include <QDebug>
#include <QLoggingCategory>

Q_LOGGING_CATEGORY(cat, "cat")

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qCDebug(cat) << "Hello World!";

    return a.exec();
}

我注意到,我可以省略 C,为我提供以下行: qDebug(cat) &lt;&lt; "Hello World!";.

执行时,两行给出相同的输出:

猫:你好世界

我还可以将 QT_LOGGING_RULES 设置为 cat=false 以关闭消息 - 在两种变体中。 如果结果实际上相同,我为什么要使用 qCDebug 而不是 qDebug?

【问题讨论】:

    标签: qt


    【解决方案1】:

    查看两个宏的代码会发现差异:

    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"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-13
      • 1970-01-01
      • 1970-01-01
      • 2011-03-24
      • 1970-01-01
      • 1970-01-01
      • 2022-09-28
      • 2023-01-16
      相关资源
      最近更新 更多