Pointer
Pointer คืออะไร
pointer (หรือ ตัวชี้) หมายถึงตัวแปรชนิดพิเศษที่เก็บที่อยู่ของข้อมูลในหน่วยความจำ โดยหลักการทำงานของ pointer คือ
- เมื่อประกาศตัวแปรใน C++ ตัวแปรจะถูกเก็บไว้ในหน่วยความจำ แต่ละตัวแปรจะมีที่อยู่ (address) เฉพาะตัวของตัวเอง
- pointer เก็บค่าที่อยู่ของตัวแปรอื่น เปรียบเสมือน "ลูกศร" ที่ชี้ไปยังตำแหน่งของข้อมูลนั้นได้
ตัวอย่างการใช้งาน Pointer
int num = 10;
int* ptrNum = # // ptrNum ชี้ไปที่ num
// เข้าถึงค่าของ num ผ่าน ptrNum
cout << *ptrNum << endl; // แสดง 10
// เปลี่ยนแปลงค่าของ num ผ่าน ptrNum
*ptrNum = 20;
// num จะมีค่า 20
cout << num << endl; // แสดง 20
ประโยชน์ของ pointer
- Direct Memory Access Pointer ช่วยให้เข้าถึงหน่วยความจำได้โดยตรงและเปลี่ยนแปลงค่าตรงนั้นได้เลย สำคัญมากๆในงานเขียนโปรแกรมระดับลึกๆ ที่เราต้องควบคุมการใช้หน่วยความจำได้แม่นยำ
- Dynamic Memory Allocation ด้วยตัว pointer เราสามารถสั่งจัดการหน่วยความจำเพิ่มตอนที่โปรแกรมทำงานโดยใช้คำสั่งอย่าง
new
และdelete
ทำให้สร้าง data structure ที่ต้องการความยืดหยุ่น สามารถเพิ่มหรือลดขนาดพื้นที่การใช้ได้ เช่น linked list ต้นไม้ (tree) และ กราฟ (graph) - Efficiency in Passing Large Structures เวลาต้องส่งข้อมูลโครงสร้างขนาดใหญ่หรือ class ให้กับ function การใช้ pointer มีประสิทธิภาพกว่าส่งค่าปกติ (pass by value) เพราะ pointer ทำให้ function สามารถเข้าถึงข้อมูลต้นฉบับได้โดยไม่ต้องสร้างสำเนาขึ้นมาใหม่ จึงประหยัดทั้งความจำและเวลาประมวลผลได้
- Function Pointers and Callbacks ตัว Pointer อาจจะชี้ไปที่ function เองก็ได้ สิ่งนี้ทำให้เราส่ง ดีืแะรนื ต่างๆ เข้าไปยังฟังก์ชันอื่น เช่น ใช้ในการส่ง callback หรือใช้เลียนแบบ polymorphism ในภาษา C
- Facilitating Complex Data Structures Pointer สำคัญมากในการสร้าง data structure ที่ซับซ้อนอย่าง linked list, trees, และ graph เพราะตัว pointer สามารถใช้เชื่อมข้อมูลที่เกี่ยวข้องกันภายใน data structure ได้
- Array Manipulation ตัว Pointer ช่วยให้ทำงานกับ array ได้อย่างมีประสิทธิภาพ เพิ่มความยืดหยุ่นกว่าการใช้ index ใน array โดยการสามารถวนค่ากับ value ใน array และสามารถเป็นตัวแทนในการจัดการค่าได้
ประเภทของ Pointer และ Operator
ประเภทของ Pointer เราจะแยกออกจากกัน ตามการใช้งานราวๆนี้ (อันนี้เป็นการแยกประเภทจากผู้สอนเอง)
- Basic Pointer เป็นการใช้ pointer อ้างอิงไปยังตัวแปรโดยตรง
int var = 10;
int* ptr = &var; // Pointer to an integer variable
- Pointer to Pointer เป็นการใช้ pointer เก็บที่อยู่ของ pointer อีกตัวเอาไว้
int var = 10;
int* ptr = &var;
int** ptrToPtr = &ptr; // Pointer to a pointer to an integer
- Array pointer เป็นการใช้ pointer ชี้ไปยัง array หรือ element แรกของ array
int arr[5] = {1, 2, 3, 4, 5};
int* arrPtr = arr; // Pointer to the first element of the array
- Function pointer ใช้ pointer ชี้ไปยัง function
void myFunction(int a) {
// Function implementation
}
void (*functionPtr)(int) = myFunction; // Pointer to a function that takes an int and returns void
Operator ใน Pointer
โดย Operation ที่สามารถทำได้ใน Pointer นั้นก็จะสามารถใช้งาน Operation แบบ Arithmetic (การดำเนินการคณิตศาสตร์) แบบทั่วๆไปได้ แต่ก็จะมีหลักแนวคิดที่แตกต่างกับตัวแปรทั่วไปคือ มันคือตัวแปรที่เก็บไว้ทั้ง “ที่อยู่” และ “ข้อมูล” ดังนั้นมันจึงสามารถเปรียบเทียบของที่นอกเหนือจากข้อมูลได้ โดย operator ก็จะมีตั้งแต่
- Address-of Operator (
&
) ใช้สำหรับรับ memory address จากตัวแปรที่ใส่ไว้
int var = 10;
int* ptr = &var; // ptr holds the address of var
- Dereference Operator (
*
) ใช้สำหรับเข้าถึงหรือแก้ไข value ของตัวแปรที่ pointer กำลังชี้ไปยัง address นั้น
int var = 10;
*ptr = 20; // Changes the value of var to 20
** อะไรก็ตามที่ใช้ผ่าน Dereference Operator = จะเหมือนกับการเรียกใช้ตัวแปรปกติ Operator ใดๆที่เคยใช้งานร่วมกับตัวแปรประเภทนั้นได้ก็จะสามารถใช้งานได้เหมือนเดิม
- Pointer Arithmetic Operators ก็จะเป็นการใช้งานสัญลักษณ์คณิตศาสตร์ทั่ว ไปอย่าง
+
,-
,++
,--
โดย สัญลักษณ์แต่ละตัวเมื่อใช้งานร่วมกับ Address ก็จะมีความหมายแตกต่างกันไปจากเดิมคือ จะเป็นการจัดการกับ “Address” แทน หากใช้กับตัวแปร pointer โดยตรง
- Addition, Increment (+, ++) เป็นการชี้ไปยัง address ตัวถัดไป
ptr + 1; // Points to the next memory location of the type ptr is pointing to
ptr++; // Moves the pointer to the next memory location
- Subtraction, Decrement (-, --) เป็นการถอย address ไปยังตัวก่อนหน้า
ptr - 1; // Points to the previous memory location of the type ptr is pointing to
ptr--; // Moves the pointer to the previous memory location
4. Comparison Operators (==
, !=
, <
, >
, <=
, >=
) ใช้สำหรับการเปรียบเทียบ address ที่อยู่ใน pointer (หากเท่ากับ = เป็นการอ้างอิงถึง address ตำแหน่งเดียวกัน = เป็นการพูดถึงตัวแปรตัวเดียวกัน)
if (ptr1 == ptr2) {
// Executes if ptr1 and ptr2 point to the same address
}
- Assignment Operator (
=
) ใช้สำหรับการ assign address เข้ากับตัวแปร pointer เพื่อใช้สำหรับ copy address จากตัวหนึ่งไปยังตัวหนึ่งได้
ptr1 = ptr2; // ptr1 now holds the same address as ptr2
6. The nullptr
Keyword (C++11 and above) ใช้สำหรับพูดถึง null pointer ที่ทำการชี้ pointer ไปยังตำแหน่งที่ไม่มี object (no object) ได้
int* ptr = nullptr; // ptr is a null pointer
- The Arrow Operator (
->
) ใช้สำหรับเข้าถึง member ที่อยู่ภายใน Struct หรือ Class ผ่าน pointer
struct MyStruct {
int field;
};
MyStruct* ptr = new MyStruct;
ptr->field = 10; // Accesses field of object pointed to by ptr
(เดี๋ยวเราเพิ่มเติมกันในเรื่อง Struct และ Class อีกที)
Pointer และ Array
ในภาษา C++ array กับ pointer มีความสัมพันธ์กันอย่างใกล้ชิด โดยชื่อของ Array นั้นจะทำหน้าที่เหมือนตัวชี้ไปยังข้อมูลตัวแรกของ Array เราจึงสามารถใช้ pointer เพื่อเข้าถึงและจัดการข้อมูลต่างๆ ภายใน Array ได้
นี่คือการประกาศ pointer ไปยัง array
- ประกาศ pointer ชนิดเดียวกับ element ของ array และใช้
&
หาที่อยู่ของ array
int arr[5] = {1, 2, 3, 4, 5};
int* ptr = arr; // ptr ชี้ไปที่ arr[0]
// เข้าถึงค่าของ arr[0] ผ่าน ptr
cout << *ptr << endl; // 1