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.cpp14.3.ComparingPointersAndReferences/main.cpp14.4.ReferencesAndConst/main.cpp14.5.ReferencesWithRangeBasedForLoops/main.cpp