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

Static C++ Class Members ถูก Initialize เมื่อไหร่?

ภาพรวม

Static Class Members ใน C++ มีกฎการ Initialize ที่เฉพาะเจาะจง:

  • Static Data Members: ต้องมี Definition (นิยาม) ใน Global/namespace Scope พอดี 1 ครั้ง
  • Initialization เกิดขึ้น ก่อน main() เริ่มต้น (Static Initialization Phase)
  • ถ้าไม่ระบุ Initializer จะถูก Zero-initialize อัตโนมัติ
  • Constant Static Members (static const integral หรือ constexpr) สามารถ Initialize ในคลาสได้ (C++11)
  • inline static (C++17) สามารถ Define และ Initialize ในคลาสได้เลย

ลำดับการ Initialize

  1. Zero Initialization: ทุก Static/Thread-local Variables = 0/Nullptr
  2. Constant Initialization: constexpr/const variables ที่มี Constant Expression
  3. Dynamic Initialization: Static variables ที่มี Initializer ที่ไม่ใช่ Constant Expression (เรียก Constructor, Function, etc.)
  4. ลำดับใน Translation Unit เดียวกัน: ตามลำดับที่ปรากฏในโค้ด
  5. ลำดับข้าม Translation Units: Unspecified (Initialization Order Fiasco)

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

#include <iostream>
using namespace std;

class Example {
public:
    static int a;              // Declaration
    static const int MAX = 100; // C++11: In-class init OK (const integral)
    static constexpr double PI = 3.14159; // C++11: constexpr
    
    void func() {
        cout << "The value of static member a: " << a;
    }
};

// Definition (จำเป็นสำหรับ Non-const Static Members)
int Example::a = 20;  // Definition + Initialization

int main() {
    Example obj;
    obj.func();
    return 0;
}

ผลลัพธ์

The value of static member a: 20

C++17 Inline Static Members (แนะนำ)


class Modern {
public:
    inline static int count = 0;        // Define + Initialize ในคลาสได้เลย
    inline static const int MAX = 100;  // const ก็ได้
    inline static vector<int> cache;    // Non-integral types ก็ได้
    
    Modern() { count++; }
    ~Modern() { count--; }
};

Initialization Order Fiasco (ปัญหาลำดับ Init)


// File1.cpp
#include "File2.hpp"
static int x = getY() + 1;  // ใช้ y จาก File2 - อาจยังไม่ Init!

// File2.cpp
static int y = 10;
int getY() { return y; }

แก้ไข: ใช้ Function-Local Static (Meyers' Singleton)


int& getX() {
    static int x = getY() + 1;  // Init ครั้งแรกที่เรียก - Safe!
    return x;
}

สรุปการ Initialize

ประเภทIn-Class InitOut-of-Class Definitionหมายเหตุ
static int (Non-const)❌ ไม่ได้ (Pre-C++17)✅ จำเป็นC++17: inline static OK
static const int✅ ได้ (C++11)❌ ไม่ต้อง (ถ้า ODR-used ต้อง Define)Integral Type เท่านั้น
static constexpr✅ ได้ (C++11)❌ ไม่ต้องImplicitly Inline
static non-integral❌ ไม่ได้ (Pre-C++17)✅ จำเป็นC++17: inline static OK