Uwagi dotyczące wydajności
Rozważnie kompiluj wzorce
Uwagi dotyczące wydajności to bezpłatna lekcja C++ Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C++ Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C++ Academy zawiera 4 lekcji w sumie.
Kompilacja jest kosztowna
Utworzenie obiektu std::regex na podstawie łańcucha kompiluje wzorzec, co jest kosztowne. Największą korzyść daje skompilowanie go raz i ponowne używanie.
- Należy unikać konstruowania obiektu regex wewnątrz pętli.
- Należy kompilować wzorzec podczas uruchamiania programu lub przy pierwszym użyciu.
#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;
}Ponowne użycie skompilowanego wzorca
Należy skonstruować wzorzec raz, poza pętlą, i używać go ponownie dla każdego wejścia. Jego odbudowywanie przy każdej iteracji marnuje czas.
#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 dla stałych
Jeśli wzorzec nigdy się nie zmienia, należy zadeklarować go jako static const wewnątrz funkcji, aby został skompilowany dokładnie raz dla wszystkich wywołań.
#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;
}Wybór właściwej gramatyki
Wariant wyrażeń regularnych (gramatyka) wpływa na szybkość i dostępne funkcje. std::regex::ECMAScript jest domyślny i najbardziej rozbudowany, natomiast std::regex::basic lub extended są prostsze i czasami szybsze.
#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;
}Flaga optimize
Dodanie std::regex::optimize informuje silnik, aby poświęcił więcej czasu na budowanie wzorca w zamian za szybsze dopasowywanie. Opłaca się to, gdy dopasowanie jest wykonywane wiele razy.
#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;
}Unikanie katastrofalnego backtrackingu
Zagnieżdżone kwantyfikatory, takie jak (a+)+, mogą dla określonych danych wejściowych doprowadzić do wykładniczego wzrostu czasu działania. Należy wybierać prostsze i jednoznaczne wzorce.
#include <iostream>
#include <regex>
int main() {
std::regex good("a+b");
std::cout << std::boolalpha << std::regex_match("aaaab", good) << '\n';
return 0;
}Stosowanie kotwic, gdy to możliwe
Zakotwiczenie wzorca za pomocą ^ i $ pozwala silnikowi szybko zakończyć nieudaną próbę, zamiast sprawdzać każdą pozycję początkową.
#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;
}W miarę możliwości wybieraj proste narzędzia
Jeśli potrzebne jest tylko sprawdzenie stałego podłańcucha, std::string::find jest znacznie szybsze niż wyrażenie regularne. Wyrażeń regularnych należy używać wtedy, gdy rzeczywiście potrzebne jest dopasowywanie wzorca.
#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;
}Ponowne używanie obiektu dopasowania
Przy wielokrotnym wyszukiwaniu należy ponownie używać jednego obiektu std::smatch zamiast za każdym razem tworzyć nowy, aby zmniejszyć narzut.
#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;
}Zawężanie wzorca
Określone klasy znaków dopasowują się szybciej i bezpieczniej niż kropka oznaczająca dowolny znak. Należy używać [0-9] zamiast ., gdy chodzi o cyfry.
#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;
}Zmierz przed optymalizacją
Połącz zdobytą wiedzę o <chrono>: mierz czas użycia wyrażeń regularnych, aby potwierdzić, że dana zmiana rzeczywiście pomaga, zanim zostanie na stałe wprowadzona.
#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;
}Szybkie sprawdzenie
Sprawdź swoją wiedzę na temat wydajności wyrażeń regularnych.
Podsumowanie
Nauczyłeś się, jak wydajnie używać wyrażeń regularnych:
- kompiluj wzorce raz, najlepiej jako
static const, i używaj ich ponownie - wybieraj odpowiednią gramatykę i rozważ użycie
optimize - unikaj katastrofalnego wycofywania i stosuj kotwice, gdy to możliwe
- używaj prostszych narzędzi, takich jak
find, dla stałych podciągów oraz mierz wprowadzane zmiany
To kończy kurs wyrażeń regularnych.
Często zadawane pytania
Czy lekcja „Uwagi dotyczące wydajności” jest bezpłatna?
Tak — pełny tekst „Uwagi dotyczące wydajności” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C++ Academy, przejdź na CoddyKit PRO. Kurs C++ Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Uwagi dotyczące wydajności”?
Rozważnie kompiluj wzorce Ćwiczysz C++ Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć C++ Academy?
Nie wymagamy żadnego doświadczenia. C++ Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Uwagi dotyczące wydajności”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji C++ Academy?
Tak. Każda lekcja C++ Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Podstawy regex
- Grupy przechwytujące
- Wyszukiwanie i zastępowanie
- Uwagi dotyczące wydajności