0Pricing
C++ Academy · Урок

Замечания о производительности

Грамотно компилируйте шаблоны

«Замечания о производительности» — бесплатный урок C++ Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.

Компиляция требует затрат

Создание std::regex из строки компилирует шаблон, а это требует значительных затрат. Наибольший выигрыш даёт однократная компиляция с последующим повторным использованием.

  • Не создавайте регулярное выражение внутри циклов.
  • Компилируйте его при запуске или при первом использовании.
#include <iostream>
#include <regex>

int main() {
    std::regex p("\\d+");
    std::string inputs[] = {"12", "ab", "99"};
    for (const auto& s : inputs) {
        std::cout << s << ": " << std::regex_match(s, p) << '\n';
    }
    return 0;
}

Повторное использование скомпилированного шаблона

Создайте шаблон один раз вне цикла и используйте его повторно для каждого входного значения. Построение шаблона на каждой итерации тратит время впустую.

#include <iostream>
#include <regex>
#include <vector>

int main() {
    static const std::regex p("[a-z]+");
    std::vector<std::string> words = {"hello", "WORLD", "cpp"};
    int matches = 0;
    for (const auto& w : words) {
        if (std::regex_match(w, p)) ++matches;
    }
    std::cout << "Matched: " << matches << '\n';
    return 0;
}

static const для констант

Если шаблон никогда не меняется, объявите его как static const внутри функции, чтобы он компилировался ровно один раз для всех вызовов.

#include <iostream>
#include <regex>

bool isEmail(const std::string& s) {
    static const std::regex p("\\w+@\\w+\\.\\w+");
    return std::regex_match(s, p);
}

int main() {
    std::cout << std::boolalpha;
    std::cout << isEmail("a@b.com") << '\n';
    std::cout << isEmail("nope") << '\n';
    return 0;
}

Выбор подходящей грамматики

Вариант грамматики регулярных выражений влияет на скорость и доступные возможности. std::regex::ECMAScript используется по умолчанию и является самым функциональным; std::regex::basic или extended проще и иногда работают быстрее.

#include <iostream>
#include <regex>

int main() {
    std::regex p("a+", std::regex::extended);
    std::cout << std::boolalpha << std::regex_match("aaa", p) << '\n';
    return 0;
}

Флаг optimize

Добавление std::regex::optimize сообщает механизму регулярных выражений, что следует потратить больше времени на построение шаблона ради более быстрого сопоставления. Это окупается, если сопоставление выполняется много раз.

#include <iostream>
#include <regex>

int main() {
    std::regex p("\\d{3}-\\d{4}", std::regex::optimize);
    std::cout << std::boolalpha << std::regex_match("123-4567", p) << '\n';
    return 0;
}

Избегайте катастрофического возврата

Вложенные квантификаторы, такие как (a+)+, на некоторых входных данных могут привести к экспоненциальному увеличению времени работы. Предпочитайте более простые и однозначные шаблоны.

#include <iostream>
#include <regex>

int main() {
    std::regex good("a+b");
    std::cout << std::boolalpha << std::regex_match("aaaab", good) << '\n';
    return 0;
}

Используйте якоря, когда это возможно

Якоря ^ и $ позволяют механизму быстро завершить поиск с ошибкой, вместо того чтобы проверять каждую начальную позицию.

#include <iostream>
#include <regex>

int main() {
    std::regex p("^[a-z]{3}$");
    std::cout << std::boolalpha;
    std::cout << std::regex_search("abc", p) << '\n';
    std::cout << std::regex_search("abcd", p) << '\n';
    return 0;
}

По возможности выбирайте простые средства

Если Вам нужно лишь проверить фиксированную подстроку, std::string::find работает значительно быстрее регулярного выражения. Используйте регулярные выражения только для настоящего сопоставления с шаблоном.

#include <iostream>
#include <string>

int main() {
    std::string s = "hello world";
    bool has = s.find("world") != std::string::npos;
    std::cout << std::boolalpha << has << '\n';
    return 0;
}

Повторное использование объекта соответствия

При многократном поиске используйте один объект std::smatch повторно, вместо того чтобы каждый раз создавать новый, чтобы сократить накладные расходы.

#include <iostream>
#include <regex>
#include <vector>

int main() {
    static const std::regex p("(\\d+)");
    std::smatch m;
    std::vector<std::string> data = {"x1", "y22", "z333"};
    for (const auto& s : data) {
        if (std::regex_search(s, m, p)) std::cout << m[1] << ' ';
    }
    std::cout << '\n';
    return 0;
}

Сузьте шаблон

Конкретные классы символов работают быстрее и безопаснее, чем универсальная точка. Выбирайте [0-9] вместо ., когда нужны цифры.

#include <iostream>
#include <regex>

int main() {
    std::regex specific("[0-9]{2}");
    std::cout << std::boolalpha;
    std::cout << std::regex_match("42", specific) << '\n';
    std::cout << std::regex_match("ab", specific) << '\n';
    return 0;
}

Измеряйте перед оптимизацией

Объедините полученные знания о <chrono>: измеряйте время работы регулярного выражения, чтобы убедиться, что изменение действительно помогает, прежде чем принимать его.

#include <iostream>
#include <regex>
#include <chrono>

int main() {
    using namespace std::chrono;
    static const std::regex p("\\d+");
    auto s = steady_clock::now();
    int hits = 0;
    for (int i = 0; i < 1000; ++i) {
        if (std::regex_search(std::string("x") + std::to_string(i), p)) ++hits;
    }
    auto e = steady_clock::now();
    std::cout << "hits=" << hits << ", timed: " << ((e - s).count() >= 0) << '\n';
    return 0;
}

Быстрая проверка

Проверьте своё понимание производительности регулярных выражений.

Повторение

Вы научились эффективно использовать регулярные выражения:

  • компилировать шаблоны один раз, в идеале как static const, и повторно использовать их
  • выбирать подходящую грамматику и рассматривать возможность использования optimize
  • избегать катастрофического возврата и по возможности использовать якоря
  • использовать более простые инструменты, например find, для фиксированных подстрок и измерять изменения

На этом курс «Регулярные выражения» завершен.

Часто задаваемые вопросы

Урок «Замечания о производительности» бесплатный?

Да — полный текст урока «Замечания о производительности» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.

Чему я научусь в уроке «Замечания о производительности»?

Грамотно компилируйте шаблоны Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C++ Academy?

Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Замечания о производительности»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C++ Academy?

Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Основы regex
  2. Группы захвата
  3. Поиск и замена
  4. Замечания о производительности
← Назад к C++ Academy