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

ตัวลบแบบกำหนดเองและฟังก์ชันสร้าง

ใช้ std::make_unique, std::make_shared และตัวลบแบบกำหนดเองกับทรัพยากรที่ไม่ใช่หน่วยความจำ

บทเรียน 4 จาก 413 ขั้นตอน

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

เหตุใดจึงต้องใช้ตัวลบแบบกำหนดเอง

ทรัพยากรไม่ได้ถูกคืนด้วย delete ทุกชนิด ตัวจัดการไฟล์ ซ็อกเก็ต ทรัพยากรเฉพาะของ OS และอาร์เรย์ ล้วนต้องใช้ฟังก์ชันทำความสะอาดที่แตกต่างกัน

ตัวลบเริ่มต้นสำหรับ unique_ptr

โดยค่าเริ่มต้น unique_ptr<T> จะใช้ delete สำหรับอาร์เรย์ ให้ใช้ unique_ptr<T[]> ซึ่งจะเรียก delete[]

การระบุตัวลบแบบกำหนดเอง

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

auto closer = [](FILE* f) { if (f) std::fclose(f); };
std::unique_ptr<FILE, decltype(closer)> file(
    std::fopen("data.txt", "r"), closer);

ตัวลบสำหรับ shared_ptr

shared_ptr จัดเก็บตัวลบไว้ในบล็อกควบคุม ชนิดของตัวลบจะถูกลบออกจากชนิด ดังนั้นชนิดของ shared_ptr เองจึงไม่เปลี่ยนแปลง

std::shared_ptr<FILE> file(
    std::fopen("data.txt", "r"),
    [](FILE* f) { if (f) std::fclose(f); }
);

กรณีการใช้งานตัวลบแบบกำหนดเองที่พบบ่อย

ตัวอย่างจากการใช้งานจริง:

  • ตัวจัดการของไลบรารี C (FILE*, sqlite3*, ตัวจัดการ curl)
  • ทรัพยากรของ OS (HANDLE บน Windows, fd บน Unix)
  • พูลหน่วยความจำแบบกำหนดเอง
  • ออบเจ็กต์ภายนอกที่นับการอ้างอิง

std::make_unique (C++14)

วิธีที่แนะนำสำหรับสร้าง unique_ptr วิธีนี้ส่งต่ออาร์กิวเมนต์ไปยังตัวสร้างและหลีกเลี่ยงการใช้ new ดิบ

auto p = std::make_unique<Widget>(arg1, arg2);

เหตุใดจึงต้องใช้ make_unique

มีประโยชน์สามประการ:

  • ความปลอดภัยต่อข้อยกเว้น — ไม่มี new ดิบในโค้ดของผู้ใช้
  • ไม่ต้องพิมพ์ชื่อชนิดซ้ำสองครั้ง
  • ไม่สามารถส่งพอยน์เตอร์ดิบให้กับ unique_ptr สองตัวโดยไม่ตั้งใจ

std::make_shared

สำหรับ shared_ptr แล้ว make_shared จะจัดสรรบล็อกควบคุมและออบเจ็กต์ในการจัดสรรบนฮีปครั้งเดียว จึงเร็วกว่าการจัดสรรแยกกัน

auto p = std::make_shared<Widget>(arg1, arg2);

เมื่อ make_shared มีข้อเสีย

การจัดสรรครั้งเดียวหมายความว่าหน่วยความจำของออบเจ็กต์จะถูกคืนก็ต่อเมื่อ weak_ptr ทั้งหมดถูกทำลายไปแล้วด้วย หาก weak_ptr ของคุณมีอายุยืนยาวกว่า shared_ptr ให้เลือกใช้การสร้างแบบสองขั้นตอน

การใช้ตัวลบแบบกำหนดเองร่วมกับ make

make_unique และ make_shared ไม่รับตัวลบแบบกำหนดเองโดยตรง ในกรณีนั้นให้สร้างพอยน์เตอร์อัจฉริยะด้วยตนเอง

// make_shared cannot take a deleter
std::shared_ptr<FILE> file(
    std::fopen("data.txt", "r"),
    [](FILE* f) { if (f) std::fclose(f); }
);

ข้อควรระวัง: ชนิดของแลมบ์ดาในอาร์กิวเมนต์แม่แบบ

แลมบ์ดาแต่ละตัวมีชนิดเฉพาะตัว สำหรับ unique_ptr ให้ใช้ decltype(my_deleter) เมื่อประกาศ หรือใช้ฟังก์ชันที่มีชื่อหรือพอยน์เตอร์ฟังก์ชันเพื่อให้ชนิดต่าง ๆ เรียบง่าย

ตรวจสอบความเข้าใจ

ฟังก์ชันโรงงานใดทำให้คุณสามารถจัดสรร std::shared_ptr และบล็อกควบคุมในการจัดสรรบนฮีปครั้งเดียว

สรุปทบทวน

ใช้ make_unique และ make_shared สำหรับกรณีทั่วไป เมื่อทรัพยากรต้องการการจัดการมากกว่า delete ให้ระบุตัวลบแบบกำหนดเอง (แลมบ์ดาหรือฟังก์ชัน) เช่น ตัวจัดการไฟล์ ออบเจ็กต์ของ OS หรือการทำความสะอาดของไลบรารี C

เริ่มต้นได้ฟรี

เรียนรู้ C++ ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
51
บทเรียน
203

คำถามที่พบบ่อย

บทเรียน “ตัวลบแบบกำหนดเองและฟังก์ชันสร้าง” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ตัวลบแบบกำหนดเองและฟังก์ชันสร้าง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C++ Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ตัวลบแบบกำหนดเองและฟังก์ชันสร้าง”

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

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

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

บทเรียน “ตัวลบแบบกำหนดเองและฟังก์ชันสร้าง” ใช้เวลานานแค่ไหน

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

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

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

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

  1. เหตุใดพอยน์เตอร์อัจฉริยะจึงมาแทน new และ delete แบบดิบ
  2. unique_ptr และการครอบครองแต่เพียงผู้เดียว
  3. shared_ptr และ weak_ptr กับการครอบครองร่วมกัน
  4. ตัวลบแบบกำหนดเองและฟังก์ชันสร้าง
← กลับไปที่ C++ Academy