性能说明
合理编译模式
性能说明 是 CoddyKit 上的免费 C++ Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 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;
}优化标志
添加 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等更简单的工具,并测量更改的效果
正则表达式课程到此结束。
常见问题解答
「性能说明」课时是免费的吗?
是的 — 「性能说明」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C++ Academy 课程的其余内容,请升级到 CoddyKit PRO。 C++ Academy 课程共包含 4 节课。
「性能说明」这节课中我会学到什么?
合理编译模式 你通过在浏览器中直接运行的动手代码来练习 C++ Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C++ Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C++ Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「性能说明」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C++ Academy 课中编写并运行代码吗?
能。每节 C++ Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。