0Pricing
C++ Academy · บทเรียน

ข้อสังเกตด้านประสิทธิภาพ

คอมไพล์รูปแบบอย่างเหมาะสม

ข้อสังเกตด้านประสิทธิภาพ เป็นบทเรียน C++ Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C++ Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน

การคอมไพล์มีต้นทุนสูง

การสร้าง std::regex จากสตริงจะคอมไพล์รูปแบบ ซึ่งมีต้นทุนสูง วิธีที่ช่วยได้มากที่สุดคือคอมไพล์เพียงครั้งเดียวแล้วนำกลับมาใช้ซ้ำ

  • หลีกเลี่ยงการสร้าง 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;
}

ค่าคงที่แบบคงอยู่

สำหรับรูปแบบที่ไม่เคยเปลี่ยน ให้ประกาศเป็นค่าคงที่แบบคงอยู่ภายในฟังก์ชัน เพื่อให้คอมไพล์เพียงครั้งเดียวตลอดการเรียกใช้ทั้งหมด

#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;
}

เลือกไวยากรณ์ที่เหมาะสม

รูปแบบไวยากรณ์ของ regex มีผลต่อความเร็วและความสามารถ 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 จะเร็วกว่า regex มาก ควรใช้ regex กับการจับคู่รูปแบบที่จำเป็นจริง ๆ

#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 ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C++ Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ข้อสังเกตด้านประสิทธิภาพ”

คอมไพล์รูปแบบอย่างเหมาะสม คุณปฏิบัติ C++ Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C++ Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C++ Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “ข้อสังเกตด้านประสิทธิภาพ” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C++ Academy นี้ได้ไหม

ได้ บทเรียน C++ Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. พื้นฐาน regex
  2. กลุ่มจับคู่
  3. การค้นหาและแทนที่
  4. ข้อสังเกตด้านประสิทธิภาพ
← กลับไปที่ C++ Academy