คู่มือ C++ สมัยใหม่
คู่มือการเรียนนี้มีวัตถุประสงค์เพื่อให้ผู้พัฒนาที่มีประสบการณ์ได้รับข้อมูลอ้างอิงอย่างรวดเร็วเกี่ยวกับคุณสมบัติใหม่ของ C++11/14/17/20 โดยครอบคลุมการปรับปรุงด้านความสามารถในการใช้งานของภาษา ประสิทธิภาพในช่วงเวลาทำงาน โครงสร้างข้อมูลใหม่ ตัวชี้อัจฉริยะและการจัดการหน่วยความจำ การจัดรูปแบบแบบสม่ำเสมอ การเขียนโปรแกรมแบบขนาน และบทนำสำหรับ C++20
ภาพรวมคอร์สเรียน
📚 สรุปเนื้อหา
คู่มือการเรียนนี้ออกแบบมาเพื่อให้ผู้พัฒนาที่มีประสบการณ์ได้ใช้เป็นแนวทางย่อสำหรับคุณสมบัติใหม่ของ C++11/14/17/20 โดยเนื้อหาครอบคลุมการปรับปรุงด้านความสะดวกในการใช้งานของภาษา การปรับปรุงประสิทธิภาพในเวลาทำงาน การใช้คอนเทนเนอร์ใหม่ ชี้แจงตัวชี้วัดและจัดการหน่วยความจำ แบบแสดงรูปแบบ (Regular Expressions) การเขียนโปรแกรมแบบขนาน และการทบทวนลักษณะสำคัญของ C++20
เรียนรู้อย่างรวดเร็วเกี่ยวกับ C++11/14/17/20 และก้าวข้ามสู่โลกของการเขียนโปรแกรมแบบสมัยใหม่ของภาษา C++
ผู้เขียน: โอ่ว เฉียงกุน (Ou Changkun)
คำขอบคุณ: อนุญาตภายใต้ข้อกำหนดแบบ CC BY-NC-ND 4.0 ขอขอบคุณผู้มีส่วนร่วมทุกคนบน GitHub และชุมชนสนับสนุนที่เกี่ยวข้อง
🎯 เป้าหมายการเรียนรู้
- ระบุและตรวจสอบสภาพแวดล้อมคอมไพเลอร์ C++ และสถาปัตยกรรมเป้าหมายโดยใช้เครื่องมือจากบรรทัดคำสั่ง
- อธิบายความเข้ากันได้ของมาตรฐานและประวัติที่ทับซ้อนกันระหว่างภาษา C (C89, C99, C11) และภาษา C++ (C++98, C++1x)
- ใช้หัวไฟล์
extern "C"และกระบวนการคอมไพล์หลายขั้นตอน เพื่อจัดการการเชื่อมต่อข้ามภาษาอย่างมีประสิทธิภาพ - แก้ไขความไม่แน่นอนของตัวชี้ (pointer ambiguity) โดยใช้
nullptrและใช้constexprและif constexprเพื่อสร้างตรรกะในขณะคอมไพล์ - ลดความซับซ้อนของคำประกาศโดยใช้
auto,decltype, และการตั้งชื่อประเภท (using) พร้อมรักษาหลักการออกแบบเชิงวัตถุที่แข็งแรงด้วยoverrideและfinal - ออกแบบโค้ดที่มีความยืดหยุ่นสูงโดยใช้เทมเพลตแบบตัวแปร (variadic templates), นิพจน์แบบพับ (fold expressions), และการอนุมานพารามิเตอร์เทมเพลตที่ไม่ใช่ประเภท (non-type template parameter deduction)
- กำหนดและดำเนินการใช้ฟังก์ชันลัมบ์ (Lambda expressions) โดยใช้โหมดการจับข้อมูลต่างๆ (ค่า, ค่าอ้างอิง, นิพจน์, และทั่วไป)
- ใช้
std::functionและstd::bindเพื่อสร้างฟังก์ชันที่ยืดหยุ่นและแอปพลิเคชันฟังก์ชันบางส่วน - แยกประเภทนิพจน์ออกเป็น Lvalues, Prvalues, และ Xvalues และนำแนวคิดการเคลื่อนย้ายทรัพยากร (Move Semantics) มาใช้เพื่อเพิ่มประสิทธิภาพการจัดการทรัพยากรในคลาส
- แยกแยะโมเดลหน่วยความจำและกรณีใช้งานของ
std::array(ขนาดคงที่, บนสแต็ก) กับstd::vector(ขนาดเปลี่ยนแปลงได้, บนฮีป)
🔹 บทเรียนที่ 1: การพัฒนาทางประวัติศาสตร์ของ C++ และสภาพแวดล้อม
ภาพรวม: บทเรียนนี้ครอบคลุมพื้นฐานทางเทคนิคของสภาพแวดล้อมการพัฒนาภาษา C++ และความสัมพันธ์ทางประวัติศาสตร์กับภาษา C โดยอธิบายว่ามาตรฐานภาษา C++ (ตั้งแต่ C++98 ถึง C++1x) มีการทับซ้อนกับมาตรฐานภาษา C (C89 ถึง C11) อย่างไร และให้รายละเอียดกลไกเฉพาะ เช่น extern "C" ที่จำเป็นต้องใช้ในการคอมไพล์และเชื่อมต่อโครงการที่รวมทั้งภาษา C และภาษา C++ ไว้ด้วยกัน
ผลลัพธ์การเรียนรู้:
- ระบุและตรวจสอบสภาพแวดล้อมคอมไพเลอร์ C++ และสถาปัตยกรรมเป้าหมายโดยใช้เครื่องมือจากบรรทัดคำสั่ง
- อธิบายความเข้ากันได้ของมาตรฐานและประวัติที่ทับซ้อนกันระหว่างภาษา C (C89, C99, C11) และภาษา C++ (C++98, C++1x)
- ใช้หัวไฟล์
extern "C"และกระบวนการคอมไพล์หลายขั้นตอน เพื่อจัดการการเชื่อมต่อข้ามภาษาอย่างมีประสิทธิภาพ
🔹 บทเรียนที่ 2: ความสะดวกในการใช้งานภาษา: โครงสร้างใหม่และเทมเพลต
ภาพรวม: บทเรียนนี้สำรวจการเปลี่ยนแปลงของภาษา C++ จาก C++11 ถึง C++20 โดยเน้นการปรับปรุงที่ช่วยเพิ่มความชัดเจนของโค้ด ความปลอดภัยด้านประเภท และความยืดหยุ่นของเทมเพลต นักเรียนจะเชี่ยวชาญคุณสมบัติโครงสร้างใหม่ เช่น การอนุมานประเภท การประเมินในขณะคอมไพล์ด้วย constexpr และเทคนิคเทมเพลตขั้นสูง เช่น เทมเพลตแบบตัวแปร (variadic templates) และนิพจน์แบบพับ (fold expressions)
ผลลัพธ์การเรียนรู้:
- แก้ไขความไม่แน่นอนของตัวชี้ (pointer ambiguity) โดยใช้
nullptrและใช้constexprและif constexprเพื่อสร้างตรรกะในขณะคอมไพล์ - ลดความซับซ้อนของคำประกาศโดยใช้
auto,decltype, และการตั้งชื่อประเภท (using) พร้อมรักษาหลักการออกแบบเชิงวัตถุที่แข็งแรงด้วยoverrideและfinal - ออกแบบโค้ดที่มีความยืดหยุ่นสูงโดยใช้เทมเพลตแบบตัวแปร (variadic templates), นิพจน์แบบพับ (fold expressions), และการอนุมานพารามิเตอร์เทมเพลตที่ไม่ใช่ประเภท (non-type template parameter deduction)
🔹 บทเรียนที่ 3: การปรับปรุงในเวลาทำงาน: ลัมบ์และแนวคิดการเคลื่อนย้ายทรัพยากร
ภาพรวม: บทเรียนนี้ครอบคลุมการปรับปรุงสำคัญในเวลาทำงานที่ปรากฏในภาษา C++ สมัยใหม่ (C++11/14) โดยเน้นโครงสร้างที่ส่งเสริมการเขียนโปรแกรมเชิงฟังก์ชันและการจัดการทรัพยากรอย่างมีประสิทธิภาพ นักเรียนจะเชี่ยวชาญฟังก์ชันลัมบ์ รวมถึงลัมบ์ที่ทั่วไปใน C++14 และการจับข้อมูลแบบนิพจน์ (expression captures) และศึกษาหลักการของแนวคิดการเคลื่อนย้ายทรัพยากร (Move Semantics) หมวดหมู่ของค่า (Value Categories) คือ Lvalues/Rvalues และการส่งต่อแบบสมบูรณ์ (Perfect Forwarding) เพื่อกำจัดการคัดลอกลึกที่ไม่จำเป็นในแอปพลิเคชันประสิทธิภาพสูง
ผลลัพธ์การเรียนรู้:
- กำหนดและดำเนินการใช้ฟังก์ชันลัมบ์โดยใช้โหมดการจับข้อมูลต่างๆ (ค่า, ค่าอ้างอิง, นิพจน์, และทั่วไป)
- ใช้
std::functionและstd::bindเพื่อสร้างฟังก์ชันที่ยืดหยุ่นและแอปพลิเคชันฟังก์ชันบางส่วน - แยกประเภทนิพจน์ออกเป็น Lvalues, Prvalues, และ Xvalues และนำแนวคิดการเคลื่อนย้ายทรัพยากร (Move Semantics) มาใช้เพื่อเพิ่มประสิทธิภาพการจัดการทรัพยากรในคลาส
🔹 บทเรียนที่ 4: คอนเทนเนอร์สมัยใหม่: std::array
ภาพรวม: บทเรียนนี้แนะนำ std::array ซึ่งเป็นคอนเทนเนอร์ที่เพิ่มเข้ามาใน C++11 แทนที่อาร์เรย์แบบดั้งเดิมของภาษา C โดยสำรวจประโยชน์ของการใช้คอนเทนเนอร์ขนาดคงที่ที่ห่อหุ้มอาร์เรย์ดิบไว้ พร้อมให้สิ่งที่ปลอดภัยกว่าและเข้ากันได้กับ STL โดยใช้การจัดสรรหน่วยความจำแบบสแต็ก
ผลลัพธ์การเรียนรู้:
- แยกแยะโมเดลหน่วยความจำและกรณีใช้งานของ
std::array(ขนาดคงที่, บนสแต็ก) กับstd::vector(ขนาดเปลี่ยนแปลงได้, บนฮีป) - ตั้งค่าและจัดการ
std::arrayอย่างถูกต้องโดยใช้เมธอดเช่น.size()และ.empty() - ใช้เครื่องมืออัลกอริธึมของ Standard Template Library (STL) และลูปแบบขอบเขต (range-based loops) กับวัตถุ
std::array
🔹 บทเรียนที่ 5: ตัวชี้อัจฉริยะและจัดการหน่วยความจำตามหลัก RAII
ภาพรวม: บทเรียนนี้แนะนำแนวคิดหลักของระบบจัดการหน่วยความจำสมัยใหม่ของภาษา C++ คือ “การได้มาซึ่งทรัพยากรในขณะเริ่มต้นการใช้งาน” (Resource Acquisition Is Initialization - RAII) บทเรียนนี้ครอบคลุมการเปลี่ยนแปลงจากการจัดการตัวชี้แบบดั้งเดิมไปสู่การจัดการอัตโนมัติโดยใช้ std::unique_ptr สำหรับการครอบครองอย่างเดียว std::shared_ptr สำหรับการแชร์แบบนับจำนวนอ้างอิง และ std::weak_ptr เพื่อตัดวงจรการอ้างอิงที่เป็นวงกลม
ผลลัพธ์การเรียนรู้:
- เข้าใจและประยุกต์ใช้หลักการ RAII เพื่อให้มั่นใจว่าทรัพยากรจะถูกปล่อยเมื่อออกจากขอบเขต
- ใช้
std::shared_ptrและstd::unique_ptrเพื่อจัดการการครอบครองแบบแชร์และแบบเดียว - ระบุและแก้ไขปัญหาการรั่วหน่วยความจำที่เกิดจากวงจรการอ้างอิงแบบเป็นวงกลมโดยใช้
std::weak_ptr
🔹 บทเรียนที่ 6: รูปแบบปกติ (Regular Expressions) และการแยกสตริง
ภาพรวม: บทเรียนนี้ครอบคลุมการใช้งานรูปแบบปกติ (Regular Expressions) โดยใช้ไลบรารีมาตรฐานของ C++11 (std::regex) และการประยุกต์ใช้จริงในการแยกข้อมูลจากคำขอ HTTP นักเรียนจะเรียนรู้ไวยากรณ์ของตัวบ่งชี้ปริมาณ (quantifiers) ใช้ std::smatch สำหรับจับผลลัพธ์ และการรวมโครงสร้างเครื่องมือเหล่านี้ไว้ในสภาพแวดล้อมเซิร์ฟเวอร์เว็บที่ใช้เทมเพลต
ผลลัพธ์การเรียนรู้:
- ระบุและนำไปใช้สัญลักษณ์พิเศษในรูปแบบปกติ (ตัวบ่งชี้ปริมาณ) เพื่อกำหนดรูปแบบของสตริง
- ใช้
std::regexและstd::smatchเพื่อตรวจสอบชื่อไฟล์และดึงข้อมูลจากสตริง - ประยุกต์ใช้ตรรกะหลักของเซิร์ฟเวอร์ รวมถึงการแยกคำขอ HTTP และการจับคู่ทรัพยากรโดยใช้โมเดลหน่วยความจำและคอนเทนเนอร์สมัยใหม่ของภาษา C++
🔹 บทเรียนที่ 7: ความสามารถในการขนาน ความเป็นขนาน และโมเดลหน่วยความจำ
ภาพรวม: บทเรียนนี้ครอบคลุมการเปลี่ยนแปลงพื้นฐานใน C++11 ที่มุ่งเน้นไปที่โมเดลการจัดการหลายเธรดอย่างเป็นมาตรฐาน ตั้งแต่การจัดการเธรดพื้นฐานและการล็อกแบบใช้ RAII ไปสู่เครื่องมือสังเคราะห์ขั้นสูงเช่น ฟิวเจอร์ (futures) และตัวแปรเงื่อนไข (condition variables) จบลงด้วยโมเดลหน่วยความจำของ C++11 ที่เข้มงวด ปฏิบัติการอะตอมิก และข้อจำกัดด้านความสอดคล้องของหน่วยความจำ
ผลลัพธ์การเรียนรู้:
- จัดการวงจรชีวิตของเธรดและป้องกันทรัพยากรที่แบ่งปันโดยใช้
std::thread,std::mutexและตัวห่อแบบ RAII (std::lock_guard,std::unique_lock) - ใช้
std::future,std::packaged_task, และstd::condition_variableเพื่อจัดการงานแบบไม่ซิงโครนัสและสื่อสารระหว่างเธรด - ใช้ประเภท
std::atomicและเลือกกลยุทธ์std::memory_orderที่เหมาะสม เพื่อให้มั่นใจว่าข้อมูลมองเห็นได้และป้องกันการสลับคำสั่งที่ไม่ถูกต้อง
🔹 บทเรียนที่ 8: ไลบรารีมาตรฐาน: การอัปเดตด้านระบบไฟล์
ภาพรวม: บทเรียนนี้สำรวจการพัฒนาของไลบรารีมาตรฐานภาษา C++ โดยเน้นฟีเจอร์ระดับสูงที่เพิ่มเข้ามาใน C++11 และมาตรฐานที่ตามมา บทเรียนนี้เน้นการเปลี่ยนแปลงจากแนวทางที่พึ่งพาแพลตฟอร์มเฉพาะหรือการเขียนโปรแกรมระดับล่าง ไปสู่เครื่องมือระดับสูงที่เป็นมาตรฐาน เช่น std::filesystem และเครื่องมือด้านความเป็นขนาน
ผลลัพธ์การเรียนรู้:
- ระบุองค์ประกอบหลักด้านความเป็นขนานที่เพิ่มเข้ามาในไลบรารีมาตรฐานใน C++11
- รับรู้ว่า
std::filesystemเป็นส่วนสำคัญสำหรับการจัดการเส้นทางและไฟล์ในยุคสมัยใหม่ - เข้าใจบทบาทของโครงสร้างที่มีความสูง (high-level abstractions) ในการทันสมัยการพัฒนาภาษา C++
🔹 บทเรียนที่ 9: คุณสมบัติสมัยใหม่หลากหลาย
ภาพรวม: บทเรียนนี้ครอบคลุมชุดคุณสมบัติที่มีผลกระทบสำคัญใน C++11 และได้รับการปรับปรุงในมาตรฐานต่อมา เพื่อเพิ่มความปลอดภัยด้านประเภท ประสิทธิภาพ และความชัดเจนของโค้ด นักเรียนจะได้เรียนรู้เกี่ยวกับประเภท long long int ข้อจำกัดการยกเว้นด้วย noexcept ข้อเสนอแนะด้านสตริงและลิตเตอร์ที่ผู้ใช้กำหนดเอง และการควบคุมการจัดวางหน่วยความจำอย่างละเอียดผ่าน alignof และ alignas
ผลลัพธ์การเรียนรู้:
- ระบุและใช้ประเภท
long long intเพื่อความแม่นยำของจำนวนเต็มที่ยาวขึ้น - ใช้คำจำกัดความ
noexceptเพื่อปรับปรุงการจัดการข้อผิดพลาด และใช้ตัวดำเนินการnoexceptเพื่อสอบถามความปลอดภัยของฟังก์ชัน - ใช้ลิตเตอร์แบบสตริงที่ไม่ต้องมีการแปลง (Raw String Literals) เพื่อลดความซับซ้อนของนิพจน์สตริง และสร้างลิตเตอร์ที่ผู้ใช้กำหนดเองเพื่อใช้กับประเภทเฉพาะ
🔹 บทเรียนที่ 10: C++20: อนาคตของภาษา
ภาพรวม: บทเรียนนี้นำเสนอเสาหลักสี่ประการของ C++20 ได้แก่ คอนเซปต์ (Concepts), โมดูล (Modules), คอร์รูทีน (Coroutines), และเรนจ์ (Ranges) คุณสมบัติเหล่านี้ถือเป็นการเปลี่ยนแปลงที่สำคัญที่สุดของภาษาตั้งแต่ C++11 โดยมุ่งเน้นการเพิ่มความปลอดภัยของเทมเพลต การเร่งความเร็วในการคอมไพล์ การเขียนโปรแกรมแบบไม่ซิงโครนัส และการประมวลผลข้อมูลแบบฟังก์ชัน
ผลลัพธ์การเรียนรู้:
- ระบุและอธิบายคุณสมบัติหลักสี่ประการที่เพิ่มเข้ามาในมาตรฐาน C++20
- อธิบายบทบาทของคอนเซปต์และเงื่อนไข (Constraints) ในการปรับปรุงการจัดการข้อผิดพลาดของเทมเพลตและการออกแบบ
- แยกแยะระหว่างแนวทางแบบหัวไฟล์ดั้งเดิมกับระบบโมดูลใหม่