กฎสาม/ห้า
จัดการการคัดลอกและการย้ายอย่างถูกต้อง
กฎสาม/ห้า เป็นบทเรียน C++ Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C++ Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน
กฎสามประการ
หากคลาสต้องมีตัวทำลายที่กำหนดเอง เกือบทุกครั้งคลาสนั้นก็มักต้องมีตัวสร้างสำเนาและการกำหนดค่าสำเนาที่กำหนดเองด้วย ทั้งสามสิ่งนี้มาคู่กัน
เหตุใดจึงมีสามประการ
คลาสที่จัดการ Resource แบบดิบต้องกำหนดวิธีทำลาย คัดลอก และกำหนดค่าให้ Resource มิฉะนั้นการคัดลอกแบบตื้นที่คอมไพเลอร์สร้างให้จะทำให้เกิดการคืนหน่วยความจำซ้ำ
#include <iostream>
class Bad {
int* p;
public:
Bad(int v) : p(new int(v)) {}
~Bad() { delete p; }
// default copy => two objects delete the same p!
};ตัวสร้างสำเนาแบบกำหนดเอง
ตัวสร้างสำเนาที่ถูกต้องจะทำ การคัดลอกแบบลึก โดยจัดสรรทรัพยากรของตนเองแทนการใช้ทรัพยากรร่วมกัน
#include <iostream>
class Box {
int* p;
public:
Box(int v) : p(new int(v)) {}
Box(const Box& o) : p(new int(*o.p)) {} // deep copy
~Box() { delete p; }
int get() const { return *p; }
};
int main() {
Box a(5);
Box b = a; // independent copy
std::cout << b.get() << "\n";
}การกำหนดค่าสำเนาแบบกำหนดเอง
การกำหนดค่าสำเนาต้องปล่อยทรัพยากรเดิม ป้องกันการกำหนดค่าให้ตัวเอง และคัดลอกค่าใหม่แบบลึก
Box& operator=(const Box& o) {
if (this != &o) { // self-assignment guard
delete p;
p = new int(*o.p);
}
return *this;
}กฎห้าประการ
C++11 เพิ่มการดำเนินการ ย้าย หากคุณกำหนดสิ่งใดสิ่งหนึ่งจากทั้งหมดห้าอย่าง ได้แก่ ตัวทำลาย ตัวสร้างสำเนา การกำหนดค่าสำเนา ตัวสร้างการย้าย และการกำหนดค่าการย้าย ก็ควรพิจารณากำหนดให้ครบทั้งห้าอย่าง
ตัวสร้างการย้าย
ตัวสร้างการย้ายจะ ขโมย ทรัพยากรจากค่าชั่วคราว แล้วปล่อยให้แหล่งที่มาว่างเปล่า ซึ่งมีต้นทุนต่ำกว่าการคัดลอกมาก
Box(Box&& o) noexcept : p(o.p) {
o.p = nullptr; // source left empty
}การกำหนดค่าการย้าย
การกำหนดค่าการย้ายจะปล่อยทรัพยากรปัจจุบัน แล้วเข้าครอบครองทรัพยากรของแหล่งที่มา
Box& operator=(Box&& o) noexcept {
if (this != &o) {
delete p;
p = o.p;
o.p = nullptr;
}
return *this;
}กำหนดให้การย้ายเป็น noexcept
การดำเนินการย้ายควรเป็น noexcept เพื่อให้คอนเทนเนอร์อย่าง std::vector ใช้งานได้อย่างปลอดภัยเมื่อจัดสรรพื้นที่ใหม่
กฎศูนย์
ทางเลือกที่ดีที่สุดคือไม่เป็นเจ้าของทรัพยากรดิบใด ๆ ใช้ std::unique_ptr std::vector หรือ std::string แล้วคุณก็ไม่ต้องกำหนดสิ่งใดเลยจากทั้งห้าอย่าง เพราะค่าเริ่มต้นของตัวแปลโปรแกรมถูกต้องอยู่แล้ว
#include <memory>
class Good {
std::unique_ptr<int> p; // owns the resource for you
public:
Good(int v) : p(std::make_unique<int>(v)) {}
// no destructor, no copy/move needed
};การลบการดำเนินการ
หากการคัดลอกไม่สมเหตุสมผล ให้ลบการดำเนินการนั้น: Box(const Box&) = delete; วิธีนี้จะทำให้ชนิดข้อมูลเป็นชนิดที่ย้ายได้เท่านั้นหรือคัดลอกไม่ได้โดยตั้งใจ
การเลือกกฎที่เหมาะสม
มุ่งใช้ กฎศูนย์ เป็นหลัก ใช้กฎห้าประการเป็นทางเลือกสำรองเฉพาะเมื่อคุณห่อหุ้มทรัพยากรดิบที่ไลบรารีมาตรฐานยังไม่รองรับจริง ๆ
ตรวจสอบความเข้าใจสั้น ๆ
ทดสอบความเข้าใจของคุณเกี่ยวกับกฎสาม/ห้าประการ
สรุป
คุณได้เรียนรู้ กฎสาม/ห้าประการ: การจัดการทรัพยากรดิบหมายถึงการกำหนดตัวทำลาย การคัดลอก และการย้ายให้สอดคล้องกัน กำหนดให้การย้ายเป็น noexcept และที่ดีที่สุดคือปฏิบัติตาม กฎศูนย์ ด้วยการใช้ชนิดข้อมูลมาตรฐานตามแนวคิด RAII และไม่ต้องกำหนดสิ่งใดเลย
คำถามที่พบบ่อย
บทเรียน “กฎสาม/ห้า” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “กฎสาม/ห้า” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C++ Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “กฎสาม/ห้า”
จัดการการคัดลอกและการย้ายอย่างถูกต้อง คุณปฏิบัติ C++ Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C++ Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C++ Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “กฎสาม/ห้า” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C++ Academy นี้ได้ไหม
ได้ บทเรียน C++ Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ