Безопасно ли использовать объект QRegExp, который объявлен как «static const»? - PullRequest
0 голосов
/ 09 января 2019

Я пытаюсь немного оптимизировать свой код и обнаружил, что мое использование QRegExp не связано с какими-либо неконстантными методами:

Код, который у меня есть:

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 -методы, которые фактически меняют объект), просмотрел код и обнаружил, что, хотя методы объявлены как const, они работают внутри изменяемого (не путайте с ключевым словом mutable) внутреннего объекта внутри (Qt использует идиому PIMPL). Итак, теперь я задаюсь вопросом, безопасно ли вызывать indexIn и cap для этого static const QRegExp объекта или нет? Эти методы, кажется, не являются реентерабельными, поскольку их использование из нескольких потоков приведет к изменению общей памяти, поэтому я думаю, что мне нужно использовать примитивы синхронизации, это правильно?

Ответы [ 2 ]

0 голосов
/ 09 января 2019

В данном конкретном случае doc fo indexIn () сообщает:

Хотя и const, эта функция устанавливает matchedLength (), capturedTexts () и pos ().

Очевидно, это означает, что indexIn() не должно быть постоянным.

Кроме этого конкретного случая, классы Qt распространяют const на свои частные указатели.

В вашем случае я бы порекомендовал использовать QRegularExpression, так как сопоставление не изменяет состояние регулярного выражения, но возвращает объект QRegularExpressionMatch.

Повторное цитирование Документация Qt :

Класс QRegularExpression, представленный в Qt 5, является большим улучшением на QRegExp, с точки зрения предлагаемых API, поддерживаемый синтаксис шаблона и скорость исполнения. Самая большая разница в том, что QRegularExpression просто содержит регулярное выражение, и оно не изменяется при совпадении запрашивается Вместо этого возвращается объект QRegularExpressionMatch, чтобы проверить результат матча и извлечь захваченный подстрока. То же самое относится к глобальному сопоставлению и QRegularExpressionMatchIterator.

Другие различия приведены ниже.

0 голосов
/ 09 января 2019

Все функции QRegExp имеют значение reentrant , однако они не threadsafe . Так что этот код хорош, если он когда-либо будет выполняться только в одном потоке.

Если вы хотите вызвать эту функцию из нескольких потоков, у вас есть два варианта:

  • Создать QMutex (и, возможно, QMutexLocker ), чтобы заблокировать этот блок кода
  • Не не делает QRegExp экземпляр static, поэтому разные потоки имеют разные экземпляры.
  • Сделать RegExp thread_local (как указал StoryTeller)

Я бы отказался от первого варианта, поскольку приостановка потоков редко является хорошей идеей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...