포스트

static

static

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;
}

주요 특징

  • 다른 소스 파일에서는 globalVarhelperFunction을 참조할 수 없다.
  • 파일 단위 캡슐화를 위해 사용된다.

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;  // 인스턴스(객체)마다 별도로 존재
};
  • 객체마다 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: 클래스 단위 공유 자원
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.