ยูเนียนและความเสี่ยง
ใช้หน่วยความจำร่วมกันระหว่างชนิด
ยูเนียนและความเสี่ยง เป็นบทเรียน C++ Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C++ Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน
ยูเนียนคืออะไร
union ทำให้สมาชิกหลายตัวใช้หน่วยความจำเดียวกันได้ โดยมีสมาชิกที่ใช้งานได้เพียงหนึ่งตัวในแต่ละครั้ง และยูเนียนจะมีขนาดเท่ากับสมาชิกที่ใหญ่ที่สุดเท่านั้น
#include <iostream>
union Number {
int i;
float f;
};
int main() {
Number n;
n.i = 42;
std::cout << n.i << "\n";
}ขนาดของยูเนียน
เนื่องจากสมาชิกใช้พื้นที่ทับซ้อนกัน sizeof ของยูเนียนจึงเท่ากับขนาดของสมาชิกที่ใหญ่ที่สุด รวมถึงพื้นที่จัดแนวที่อาจมีเพิ่ม ไม่ใช่ผลรวมของสมาชิกทั้งหมด
#include <iostream>
union Mix { char c; int i; double d; };
int main() {
std::cout << sizeof(Mix) << "\n"; // size of double (often 8)
}การเขียนสมาชิกหนึ่งและอ่านอีกสมาชิกหนึ่ง
การเขียนสมาชิกหนึ่งแล้วอ่านสมาชิกอื่นคือ ความเสี่ยงสำคัญ บิตจะถูกตีความใหม่ ซึ่งมักทำให้เกิดพฤติกรรมไม่กำหนดหรือผลลัพธ์ที่น่าประหลาดใจ
#include <iostream>
union Bits { int i; float f; };
int main() {
Bits b;
b.f = 1.0f;
std::cout << b.i << "\n"; // reads float bits as int
}สมาชิกที่ใช้งานอยู่เพียงหนึ่งเดียว
สมาชิกที่คุณเขียนล่าสุดคือสมาชิกเพียงตัวเดียวที่สามารถอ่านได้อย่างปลอดภัย คุณต้องติดตามเองว่าสมาชิกใด "ใช้งานอยู่" เพราะยูเนียนจะไม่จดจำข้อมูลนี้
#include <iostream>
union Value { int i; double d; };
int main() {
Value v;
v.d = 3.14; // d is active
std::cout << v.d << "\n";
}รูปแบบยูเนียนติดแท็ก
หากต้องการใช้ยูเนียนอย่างปลอดภัย ให้จับคู่กับ แท็ก (ชนิดแจกแจง) ซึ่งบันทึกว่าสมาชิกใดกำลังใช้งานอยู่ นี่คือแนวคิดรุ่นก่อนหน้าที่ทำด้วยตนเองของ std::variant
#include <iostream>
struct Tagged {
enum { Int, Double } tag;
union { int i; double d; };
};
int main() {
Tagged t; t.tag = Tagged::Int; t.i = 7;
if (t.tag == Tagged::Int) std::cout << t.i << "\n";
}การอ่านสมาชิกที่ถูกต้อง
ตรวจสอบแท็กก่อนอ่านทุกครั้ง การอ่านสมาชิกที่ไม่ถูกต้องจะให้ค่าขยะ
#include <iostream>
struct Tagged {
enum { Int, Double } tag;
union { int i; double d; };
};
void print(const Tagged& t) {
if (t.tag == Tagged::Int) std::cout << "int " << t.i << "\n";
else std::cout << "double " << t.d << "\n";
}
int main() { Tagged t{Tagged::Double}; t.d = 2.5; print(t); }สมาชิกที่ไม่ใช่ชนิดพื้นฐาน
การใส่สมาชิกที่มีตัวสร้างหรือตัวทำลาย (เช่น std::string) ไว้ในยูเนียน จำเป็นต้องสร้างและทำลายด้วยตนเอง ซึ่งมีโอกาสเกิดข้อผิดพลาดได้ง่าย และเป็นอีกเหตุผลหนึ่งที่ควรเลือกใช้ std::variant
ยูเนียนนิรนาม
ยูเนียนนิรนามไม่มีชื่อ โดยเข้าถึงสมาชิกของยูเนียนได้โดยตรง เหมาะสำหรับใช้ภายในโครงสร้าง แต่ยังคงต้องปฏิบัติตามกฎของสมาชิกที่ใช้งานอยู่เช่นเดิม
#include <iostream>
struct Packet {
int kind;
union { int code; char letter; };
};
int main() {
Packet p; p.kind = 1; p.code = 99;
std::cout << p.code << "\n";
}เหตุใดยูเนียนจึงมีความเสี่ยง
สรุปอันตราย:
- ไม่มีข้อมูลว่าสมาชิกใดกำลังใช้งานอยู่
- การอ่านสมาชิกที่ไม่ได้ใช้งานอยู่เป็นพฤติกรรมไม่กำหนด
- ชนิดที่ไม่ใช่ชนิดพื้นฐานต้องจัดการอายุการใช้งานด้วยตนเอง
กรณีที่ยูเนียนยังมีประโยชน์
ยูเนียนยังมีประโยชน์สำหรับงานระดับต่ำ เช่น การตีความไบต์ใหม่ การประหยัดหน่วยความจำในโค้ดระบบฝังตัวที่มีข้อจำกัด หรือการจับคู่กับโครงสร้างไบนารีแบบตายตัว สำหรับข้อมูลที่เป็น "หนึ่งชนิดจากหลายชนิด" ในการใช้งานทั่วไป ควรเลือกทางเลือกที่ปลอดภัยกว่า
มุ่งสู่ std::variant
std::variant คือยูเนียนที่ปลอดภัยด้านชนิดข้อมูล ซึ่งติดตามชนิดที่ใช้งานอยู่ให้คุณ และจะโยนข้อยกเว้นหากคุณเข้าถึงชนิดที่ไม่ถูกต้อง บทเรียนที่เหลือของหลักสูตรนี้จะสำรวจเรื่องดังกล่าว
ตรวจสอบความเข้าใจอย่างรวดเร็ว
ตรวจสอบความเข้าใจของคุณเกี่ยวกับยูเนียน
ทบทวน
คุณได้เรียนรู้เกี่ยวกับ ยูเนียน:
- สมาชิกทั้งหมดใช้บล็อกหน่วยความจำเดียวกัน
- สมาชิกที่อ่านได้อย่างถูกต้องมีเพียงสมาชิกที่เขียนล่าสุด
- ใช้แท็ก (ชนิดแจกแจง) เพื่อติดตามสมาชิกที่กำลังใช้งานอยู่
- เลือกใช้
std::variantเพื่อความปลอดภัยใน C++ สมัยใหม่
เรียนรู้ C++ ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 51
- บทเรียน
- 203
คำถามที่พบบ่อย
บทเรียน “ยูเนียนและความเสี่ยง” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ยูเนียนและความเสี่ยง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C++ Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ยูเนียนและความเสี่ยง”
ใช้หน่วยความจำร่วมกันระหว่างชนิด คุณปฏิบัติ C++ Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C++ Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C++ Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “ยูเนียนและความเสี่ยง” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C++ Academy นี้ได้ไหม
ได้ บทเรียน C++ Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- enum class แบบมีขอบเขต
- ยูเนียนและความเสี่ยง
- std::variant
- std::visit