Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

Static Variables ใน Member Functions ของ C++ ทำงานอย่างไร?

ภาพรวม

Static Variables ภายใน Member Function (หรือฟังก์ชันทั่วไป) มีลักษณะพิเศษ:

  • จัดสรรหน่วยความจำ เพียงครั้งเดียว ตลอดการรันโปรแกรม
  • มี เพียง 1 ตัว แชร์ร่วมกันทุกครั้งที่เรียกฟังก์ชัน (รวมทุกออบเจ็กต์)
  • Initialize แค่ครั้งแรกที่ผ่านบรรทัดการประกาศ
  • ค่า Default คือ 0 (สำหรับ primitive types)
  • มีอายุชีวิตจนโปรแกรมจบ (Program Lifetime)

ตัวอย่างโค้ด

#include <iostream>
using namespace std;

class Base {
public:
    void func() {
        static int a;        // Default initialize = 0
        static int b = 12;   // Explicit initialize = 12
        
        cout << "The default value of static variable a is: " << a;
        cout << "\nThe value of static variable b is: " << b;
        
        a++; b++;  // แสดงว่าคงค่าระหว่างการเรียก
    }
};

int main() {
    Base obj1;
    obj1.func();  // a=0, b=12
    
    Base obj2;
    obj2.func();  // a=1, b=13 (ค่าเพิ่มขึ้น!)
    
    obj1.func();  // a=2, b=14 (ยังคงค่าเดิม)
    
    return 0;
}

ผลลัพธ์

The default value of static variable a is: 0
The value of static variable b is: 12
The default value of static variable a is: 1
The value of static variable b is: 13
The default value of static variable a is: 2
The value of static variable b is: 14

รายละเอียดสำคัญ

  1. Shared across all objects: ไม่ใช่ต่อออบเจ็กต์ แตกต่างจาก Non-static Data Members
  2. Initialization thread-safe (C++11+): Compiler ใส่ guard code ป้องกัน race condition
  3. Scope: มองเห็นได้เฉพาะภายในฟังก์ชันนั้นๆ (Function Scope)
  4. Lifetime: Static Storage Duration (Program Lifetime)

กรณีการใช้งานทั่วไป

  • Call Counter: นับจำนวนครั้งที่ฟังก์ชันถูกเรียก
  • Caching/Memoization: เก็บผลลัพธ์ไว้ใช้ซ้ำ
  • Singleton Instance: Meyers' Singleton Pattern
  • One-time Initialization: ทำ initialization แค่ครั้งแรก

ตัวอย่าง Call Counter


void trackCalls() {
    static int count = 0;
    count++;
    cout << "Function called " << count << " times\n";
}

ข้อควรระวัง

  • ไม่ใช่ Thread-Local (ถ้าต้องการ ใช้ thread_local)
  • Destruction order ไม่แน่นอนข้าม Translation Units
  • การทดสอบ (Unit Testing) ยาก เพราะสถานะคงค่าระหว่างเทส