ข้ามไปที่เนื้อหา

Ch9: References

TL;DR: Alias Semantic: Reference (การอ้างอิง) ทำหน้าที่เป็นนามแฝง (Alias) ของตัวแปรที่มีอยู่จริง โดยทั้งตัวแปรต้นฉบับและ Reference จะใช้ที่อยู่หน่วยความจำเดียวกัน ทำให้เปรียบเสมือนตัวแปรเดียวกันที่มีสองชื่อ

⚡ Quick Reference

#include <iostream>

int main() {
    int value = 45;

    // type& ref = val - ประกาศตัวแปรอ้างอิง (Alias) ตัวแปรที่มีอยู่จริง
    int& ref_val = value;

    // const type& ref = val - ตัวอ้างอิงแบบคงที่ สามารถชี้หาค่าชั่วคราว (Rvalue) ได้
    const int& const_ref = 100; // รองรับ Rvalue เช่น เลข 100 ได้อย่างปลอดภัย

    ref_val = 50; // อัปเดตค่าของตัวแปร value ผ่านการแก้ไข ref_val

    return 0;
}

🧠 Core Concepts

  • Alias Semantic: Reference (การอ้างอิง) ทำหน้าที่เป็นนามแฝง (Alias) ของตัวแปรที่มีอยู่จริง โดยทั้งตัวแปรต้นฉบับและ Reference จะใช้ที่อยู่หน่วยความจำเดียวกัน ทำให้เปรียบเสมือนตัวแปรเดียวกันที่มีสองชื่อ
  • Immutability of Binding: Reference จะต้องถูกกำหนดค่าเริ่มต้นทันทีที่ประกาศตัวแปร และไม่สามารถเปลี่ยนไปอ้างอิงถึงตัวแปรอื่นในภายหลังได้ ซึ่งพฤติกรรมนี้จะเหมือนกับ Constant Pointer
  • Const References: การใช้ const บน Reference (const T&) จะช่วยป้องกันการแก้ไขค่าผ่านตัวแปรนามแฝงนั้น ทว่าค่าของตัวแปรต้นทางยังคงเปลี่ยนแปลงได้หากตัวแปรต้นทางไม่ได้ถูกประกาศเป็น const

⚠️ Pitfalls (Quick Scan)

ข้อผิดพลาด วิธีแก้
การประกาศ Reference โดยไม่ได้กำหนดค่าเริ่มต้น กำหนดค่าเริ่มต้นด้วยตัวแปร lvalue เสมอตอนประกาศตัวแปร
พยายามผูกตัวแปรตัวใหม่ให้กับ Reference ผ่านการระบุค่าด้วย = ระลึกไว้เสมอว่า Reference ไม่สามารถเปลี่ยนตัวแปรที่อ้างอิงได้
สั่งพิมพ์ตัวแปร Pointer โดยตรงโดยไม่ได้ทำการ Dereference ใช้เครื่องหมาย *p เพื่อ Dereference ดึงค่าจริงออกมาแสดงผล
เข้าใจผิดว่าการใช้ Const Reference จะทำให้ตัวแปรต้นฉบับแก้ไขค่าไม่ได้เลย เข้าใจว่า const จำกัดเฉพาะการเข้าถึงผ่านตัวแปร Reference นั้นเท่านั้น
เขียนไวยากรณ์ที่ไม่มีอยู่จริงอย่าง const int& const ref{var} หลีกเลี่ยงการเขียน const ต่อท้ายสัญลักษณ์ & เพราะการอ้างอิงเป็นค่าคงที่อยู่แล้ว
ใช้ตัวแปรแบบคัดลอก (Copy) ในลูปเมื่อต้องการแก้ไขค่าสมาชิก ใช้ auto& เสมอเมื่อต้องการแก้ไขข้อมูลใน Container ระหว่างวนลูป (Lecture 14.5)

📖 Full Details

Cause → Effect → Fix พร้อม timestamp (คลิกเพื่อดู) * **การประกาศ Reference โดยไม่ได้กำหนดค่าเริ่มต้น** -> **เกิด Compile-time error แจ้งเตือนว่าต้องการค่าเริ่มต้น** -> **กำหนดค่าเริ่มต้นด้วยตัวแปร lvalue เสมอตอนประกาศตัวแปร (09:22)** * **พยายามผูกตัวแปรตัวใหม่ให้กับ Reference ผ่านการระบุค่าด้วย `=`** -> **เป็นการเขียนทับค่าของตัวแปรเดิมแทนที่จะเปลี่ยนแอดเดรสที่ชี้** -> **ระลึกไว้เสมอว่า Reference ไม่สามารถเปลี่ยนตัวแปรที่อ้างอิงได้ (06:30)** * **สั่งพิมพ์ตัวแปร Pointer โดยตรงโดยไม่ได้ทำการ Dereference** -> **โปรแกรมจะแสดงตำแหน่งหน่วยความจำแทนที่จะแสดงค่าจริง** -> **ใช้เครื่องหมาย `*p` เพื่อ Dereference ดึงค่าจริงออกมาแสดงผล (05:56)** * **เข้าใจผิดว่าการใช้ Const Reference จะทำให้ตัวแปรต้นฉบับแก้ไขค่าไม่ได้เลย** -> **ตัวแปรต้นทางยังคงแก้ไขค่าได้ตามปกติผ่านชื่อตัวแปรของตัวเอง** -> **เข้าใจว่า `const` จำกัดเฉพาะการเข้าถึงผ่านตัวแปร Reference นั้นเท่านั้น (12:22)** * **เขียนไวยากรณ์ที่ไม่มีอยู่จริงอย่าง `const int& const ref{var}`** -> **เกิด Compile-time error เนื่องจากไวยากรณ์ไม่มีอยู่จริงใน C++** -> **หลีกเลี่ยงการเขียน `const` ต่อท้ายสัญลักษณ์ `&` เพราะการอ้างอิงเป็นค่าคงที่อยู่แล้ว (12:14)** * **ใช้ตัวแปรแบบคัดลอก (Copy) ในลูปเมื่อต้องการแก้ไขค่าสมาชิก** -> **ค่าที่เปลี่ยนแปลงส่งผลต่อตัวแปรชั่วคราวเท่านั้น ไม่กระทบถึงข้อมูลต้นฉบับ** -> **ใช้ `auto&` เสมอเมื่อต้องการแก้ไขข้อมูลใน Container ระหว่างวนลูป (Lecture 14.5)**

📎 Repo Files

  • 14.2.DeclaringAndUsingReferences/main.cpp
  • 14.3.ComparingPointersAndReferences/main.cpp
  • 14.4.ReferencesAndConst/main.cpp
  • 14.5.ReferencesWithRangeBasedForLoops/main.cpp