0Pricing
C++ Academy · 课时

性能说明

合理编译模式

性能说明 是 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 反馈 — 无需本地设置。

此课程中的所有课时

  1. regex 基础
  2. 捕获组
  3. 搜索与替换
  4. 性能说明
← 返回 C++ Academy