使用声明为“静态常量”的QRegExp对象是否安全?

时间:2019-01-09 08:36:38

标签: c++ qt

我尝试对代码进行一些优化,发现我对QRegExp的使用不涉及它的任何非const方法:

我拥有的代码:

QString parse(const QString &data) {
    static const QRegExp DATA_REGEXP(QStringLiteral("^(\\w{4}) (\\w{4}) SN=(\\w*)"));

    if (DATA_REGEXP.indexIn(data) != -1) {
        const QString vendorId = DATA_REGEXP.cap(1);
        const QString modelId = DATA_REGEXP.cap(2);
        const QString serial = DATA_REGEXP.cap(3);

        // ...
    }

    // ...
}

我想知道这怎么可能(具有const方法实际上是在改变对象),检查了the code并发现,即使方法被声明为const,它们仍然在内部使用可变对象(不要与mutable关键字混淆)私有对象(Qt使用PIMPL习惯用语)。因此,现在我想知道在此indexIn对象上调用capstatic const QRegExp是否安全?这些方法似乎并不是可重用的,因为它们在多个线程中的使用将导致共享内存的更改,所以我想我必须使用同步原语,对吗?

2 个答案:

答案 0 :(得分:2)

QRegExp的所有功能都是 reentant ,但不是threadsafe。因此,如果仅在单个线程中运行,则此代码会很好。

如果要从多个线程调用此函数,则有两个选择:

  • 创建一个QMutex(可能还有QMutexLocker)来锁定此代码块
  • 不要创建QRegExp实例static,所以不同的线程具有不同的实例。
  • 进行RegExp thread_local(如StoryTeller所指出的那样)

我会避免第一种选择,因为暂停线程很少是一个好主意。

答案 1 :(得分:2)

在这种特殊情况下,doc fo indexIn()指出:

  

尽管是const,但此函数设置matchLength(),capturedTexts()和pos()。

很明显,这意味着indexIn()不应为常量。

除了这种特殊情况外,Qt类的确将const传播到其私有指针。

对于您而言,我建议您使用QRegularExpression,因为进行匹配不会修改正则表达式的状态,而是返回一个QRegularExpressionMatch对象。

再次引用Qt documentation

  

Qt 5中引入的QRegularExpression类是一个很大的改进   在QRegExp上,就提供的API而言,支持的模式语法和   执行速度。最大的区别是QRegularExpression   只包含一个正则表达式,匹配时不会对其进行修改   被要求。而是返回QRegularExpressionMatch对象,   为了检查比赛结果并提取捕获的   子字符串。全局匹配和   QRegularExpressionMatchIterator。

     

其他区别如下。