C++ static 키워드 정리
1. static 키워드란?
static 키워드는 C++에서 저장 기간(Storage Duration)과 접근 범위(Linkage)를 제어하는 키워드로, 변수와 함수, 클래스 멤버 등에 사용된다.
2. static의 주요 역할
| 사용 위치 | 의미 |
|---|
| 전역 변수, 함수 앞 | 내부 연결성(Internal Linkage): 해당 소스 파일 내에서만 접근 가능하도록 제한 |
| 지역 변수 앞 | 정적 수명(Static Duration): 함수가 종료되어도 값이 유지됨 |
| 클래스 멤버 변수/함수 앞 | 정적 멤버(Static Member): 클래스에 속하지만 객체에 종속되지 않음(클래스 변수/클래스 함수) |
3. 사용 위치별 상세 설명
3.1. 전역 변수와 함수 앞에 static
해당 소스 파일(.cpp) 내에서만 접근 가능하도록 제한하는 역할을 한다. 이를 내부 연결성(Internal Linkage)이라고 한다.
1
2
3
4
5
| static int globalVar = 10; // 이 파일 내에서만 접근 가능
static void helperFunction() {
std::cout << "This is a static function" << std::endl;
}
|
주요 특징
- 다른 소스 파일에서는
globalVar와 helperFunction을 참조할 수 없다. - 파일 단위 캡슐화를 위해 사용된다.
3.2. 지역 변수 앞에 static
함수가 종료되어도 변수의 값이 유지되며, 프로그램 종료 시까지 살아 있다.
1
2
3
4
5
| void counter() {
static int count = 0; // 초기화는 딱 한 번만 실행됨
count++;
std::cout << "Count: " << count << std::endl;
}
|
주요 특징
- 처음 호출될 때만 초기화되고 이후에는 값이 유지된다.
- 함수 호출 횟수 기록, 상태 유지와 같은 용도로 사용된다.
3.3. 클래스 멤버 변수/함수 앞에 static
(1) 정적 멤버 변수 (클래스 변수)
모든 객체가 공유하는 변수이다. 클래스당 하나만 생성되며, 객체가 없어도 접근 가능하다.
1
2
3
4
5
6
7
8
| class Player {
public:
static int playerCount;
Player() { playerCount++; }
};
int Player::playerCount = 0; // 반드시 초기화 필요
|
(2) 정적 멤버 함수 (클래스 함수)
객체 없이 클래스 자체로 호출 가능하며, 정적 멤버 변수나 클래스 전역적인 동작을 수행할 때 사용된다.
1
2
3
4
5
6
7
8
| class Player {
public:
static void printPlayerCount() {
std::cout << "Player Count: " << playerCount << std::endl;
}
};
Player::printPlayerCount(); // 객체 없이 호출 가능
|
주요 특징
- 클래스 단위로 공유되는 데이터나 기능을 만들 때 사용된다.
- 모든 객체가 공통으로 사용하는 설정값, 상태값 등을 관리할 때 유용하다.
4. static 변수는 어디에 할당되는가?
초기화 여부에 따라 메모리 위치가 달라진다.
| 위치 | 초기화 여부 | 메모리 영역 |
|---|
| 전역(파일 스코프) static 변수 | 초기화 O | .data |
| | 초기화 X | .bss |
| 지역 static 변수 | 초기화 O/X | .data 또는 .bss |
| 클래스 static 멤버 변수 | 초기화 O/X | .data 또는 .bss |
.data 영역: 초기화된 전역/정적 변수들이 저장된다..bss 영역: 초기화되지 않은 전역/정적 변수들이 저장되며, 0으로 초기화된다.
지역 static 변수는 비록 지역 변수처럼 보이지만, 정적 수명(Static Duration)을 가지므로 데이터 영역(.data, .bss)에 저장된다.
5. 클래스의 static 멤버 변수는 왜 공유되는가?
일반 멤버 변수와 비교
1
2
3
4
| class Player {
public:
int score; // 인스턴스(객체)마다 별도로 존재
};
|
1
2
3
4
5
6
| class Player {
public:
static int playerCount;
};
int Player::playerCount = 0;
|
Player::playerCount는 클래스당 하나만 존재한다.- 모든 객체가 이 하나의 변수를 참조한다.
메모리 구조 상으로 보면 다음과 같다:
1
2
3
4
5
6
7
| .data / .bss (데이터 영역)
└── Player::playerCount // 단 하나만 존재
힙(Heap) or 스택(Stack)
├── Player p1
├── Player p2
└── Player p3
|
즉, Player의 객체가 여러 개 만들어져도 playerCount는 하나만 존재하고, 모든 객체가 이를 참조하는 방식이다.
1
2
| Player::playerCount = 10; // 클래스명::변수명 형태로 접근 (권장)
p1.playerCount = 20; // 객체로도 접근 가능 (비권장)
|
6. 요약
| 위치 | 역할 | 주요 특징 |
|---|
| 전역 변수, 함수 앞 | 내부 연결성(Internal Linkage) | 해당 파일 내에서만 접근 가능 |
| 지역 변수 앞 | 정적 수명(Static Duration) | 함수 호출 종료 후에도 값 유지 |
| 클래스 멤버 앞 | 정적 멤버(Static Member) | 객체와 무관, 클래스 단위로 공유 |
7. 주의사항
- 지역
static 변수 초기화는 한 번만 실행된다. - 정적 멤버 변수는 클래스 외부에서 반드시 초기화해줘야 한다.
- 전역
static 변수 남발하면 코드 가독성과 유지보수성이 떨어질 수 있다.
8. 결론
static은 저장 기간과 접근 범위를 제어하는 중요한 키워드이다. 상황에 맞게 적절하게 사용하는 것이 중요하다.
- 전역 static: 파일 단위 캡슐화
- 지역 static: 함수 상태 유지
- 클래스 static: 클래스 단위 공유 자원