ภาพรวม
Reference Variable (ตัวแปรอ้างอิง) คือชื่อเรียกอื่น (Alias) ของตัวแปรที่มีอยู่แล้ว ไม่ใช่ตัวแปรใหม่ ไม่มีหน่วยความจำแยกต่างหาก การดำเนินการกับ Reference คือการดำเนินการกับตัวแปรต้นฉบับโดยตรง
คุณสมบัติหลัก
- ต้อง Initialize ตอนประกาศ (ไม่สามารถประกาศแยกได้)
- ไม่สามารถเปลี่ยนอ้างอิงไปตัวแปรอื่นได้ (Re-bind ไม่ได้)
- ไม่สามารถเป็น NULL ได้ (ต้องอ้างอิง Object จริงเสมอ)
- ใช้ Operator
&ในการประกาศ - Syntax:
Type& refName = existingVar;
ตัวอย่างพื้นฐาน
#include <iostream>
using namespace std;
int main() {
int a = 8;
int& b = a; // b เป็น Reference ของ a
cout << "The variable a: " << a << "\n";
cout << "The reference variable b: " << b << "\n";
b = 20; // เปลี่ยนค่าผ่าน Reference
cout << "After b = 20:\n";
cout << "a = " << a << "\n"; // a กลายเป็น 20 ด้วย!
cout << "b = " << b << "\n";
return 0;
}
ผลลัพธ์
The variable a: 8
The reference variable b: 8
After b = 20:
a = 20
b = 20
ประเภทของ References
1. Lvalue Reference (Classic) - Type&
int x = 10;
int& ref = x; // OK
int& ref2 = 20; // ❌ Error: Temporary (Rvalue) - ต้องเป็น const
const int& cref = 20; // OK: const lvalue reference binds to temporary
2. Rvalue Reference (C++11) - Type&&
int&& rref = 20; // OK: Bind to Temporary
int&& rref2 = x; // ❌ Error: x is Lvalue
int&& rref3 = std::move(x); // OK: Cast Lvalue to Rvalue
3. Forwarding Reference (Universal Reference) - T&& ใน Template
template
void func(T&& param) { // Forwarding Reference (ไม่ใช่ Rvalue Ref เสมอไป)
// Perfect Forwarding
std::forward(param);
}
การใช้งานหลัก
1. Function Parameters (Pass by Reference)
// Pass by Reference - หลีกเลี่ยง Copy, สามารถ Modify ได้
void swap(int& a, int& b) {
int temp = a; a = b; b = temp;
}
// Pass by Const Reference - หลีกเลี่ยง Copy, Read-Only
void print(const string& s) {
cout << s; // ไม่ Copy String
}
2. Return by Reference
// Return Reference to Existing Object (Static/Global/Member)
int& getElement(vector& v, size_t index) {
return v[index]; // Reference to Element in Vector
}
// ❌ Dangerous: Return Reference to Local
int& badFunc() {
int local = 10;
return local; // Dangling Reference! UB!
}
3. Range-based For Loop
vector vec = {1, 2, 3};
for (int& x : vec) { // Reference - Modify Original
x *= 2;
}
for (const int& x : vec) { // Const Reference - Read Only, No Copy
cout << x << " ";
}
Reference vs Pointer
| คุณสมบัติ | Reference (T&) | Pointer (T*) |
|---|---|---|
| Syntax | int& r = x; | int* p = &x; |
| Null | ไม่ได้ (Always Valid) | ได้ (nullptr) |
| Reassignment | ไม่ได้ (Bind Once) | ได้ (Point to Elsewhere) |
| Dereference | Implicit (Auto) | Explicit (*p) |
| Memory Overhead | ไม่มี (Alias) | มี (Pointer Size) |
| Array/Pointer Arithmetic | ไม่ได้ | ได้ |
Best Practices
- Default to Pass by Const Reference สำหรับ Parameters (ยกเว้น Small Types: int, char, pointers)
- ใช้
std::move/ Rvalue References สำหรับ Move Semantics - ไม่ Return Reference to Local Variables
- ใช้ References สำห Operator Overloading (
operator=,operator[], etc.) - C++20: ใช้
std::spanแทน Pointer+Size สำหรับ Array Views