C++에서 static은 변수, 함수, 클래스 멤버에 각각 다른 의미로 사용되지만, 핵심은 항상 동일합니다:
static은 어떤 대상을 **“한 번만 생성되고, 프로그램의 전체 생명주기 동안 유지”**되게 만듭니다.
함수 내부에서 선언된 static 변수는 프로그램 시작 시 한 번만 초기화되고, 함수가 종료되어도 값이 유지됩니다.
#include <iostream>
int counter() {
static int count = 0; // 처음 호출 시에만 초기화
return ++count;
}
int main() {
std::cout << counter() << std::endl; // 1
std::cout << counter() << std::endl; // 2
std::cout << counter() << std::endl; // 3
return 0;
}
특징: 지역 변수의 스코프를 유지하면서 전역 변수의 수명을 가집니다. 스레드 안전한 초기화가 보장됩니다.
파일 스코프에서 static으로 선언된 변수나 함수는 해당 파일 내에서만 접근 가능합니다.
// file1.cpp
static int internal_var = 100; // 이 파일에서만 접근 가능
static void internal_function() { // 이 파일에서만 접근 가능
std::cout << "Internal function" << std::endl;
}
int global_var = 200; // 다른 파일에서도 extern으로 접근 가능
용도: 내부 구현 세부사항을 숨기고, 이름 충돌을 방지합니다. C++에서는 anonymous namespace 사용을 더 권장합니다.
클래스의 모든 객체가 공유하는 변수입니다. 객체를 생성하지 않아도 접근할 수 있습니다.
class MyClass {
private:
static int count; // 선언
int id;
public:
MyClass() : id(++count) {}
static int getCount() { // 정적 멤버 함수
return count;
}
int getId() const { return id; }
};
// 클래스 외부에서 정의 (필수)
int MyClass::count = 0;
int main() {
std::cout << MyClass::getCount() << std::endl; // 0
MyClass obj1, obj2, obj3;
std::cout << MyClass::getCount() << std::endl; // 3
std::cout << obj2.getId() << std::endl; // 2
std::cout << obj1.getId() << std::endl; // 1
std::cout << obj3.getId() << std::endl; // 3
return 0;
}
객체 없이 호출할 수 있는 함수로, 비정적 멤버에는 접근할 수 없습니다.
class MathUtils {
public:
static int add(int a, int b) {
return a + b;
}
static double pi() {
return 3.14159;
}
};
int main() {
// 객체 생성 없이 직접 호출
int result = MathUtils::add(5, 3);
double pi_value = MathUtils::pi();
return 0;
}
class Resource {
private:
static std::vector<int> data; // 정적 멤버
public:
static void initialize() {
if (data.empty()) {
data = {1, 2, 3, 4, 5};
std::cout << "Static data initialized" << std::endl;
}
}
static const std::vector<int>& getData() {
return data;
}
};
// 정적 멤버 정의
std::vector<int> Resource::data;