[static 키워드] 02_정적 멤버 변수
static 멤버 변수는 클래스 객체가 생성되기 전, 프로그램 실행 시 Data 영역이나 BSS 영역에 할당 되며, 프로그램 실행 기간 동안 유지되는 변수입니다.
정적 멤버 변수는 프로그램 전체에서 단 하나의 공유 메모리 안에서 존재합니다.
즉, 어떤 객체를 생성해도 정적 멤버 변수는 같은 주소를 갖고, 객체와 독립적으로 존재한다는 뜻입니다.
따라서, 객체의 이름으로도 접근 가능하지만, 클래스 이름으로도 접근이 가능합니다.
때문에, 모든 객체들이 공통적으로 알아야 하는 데이터를 공유하는데 사용합니다.
초기화
초기화의 경우에는 클래스 객체가 생성되기 전에 해야 하기 때문에, 전역 공간에서 초기화를 해주어야 합니다.
초기화는 클래스의 이름으로 접근해서 초기화 합니다. (아직 객체가 생성되지 않았기 때문)
자료형 클래스이름::정적멤버변수이름 = 초기화할값;
요약
- 메모리: 프로그램 실행시 초기화 값이 있는 경우 Data 영역에, 초기화 값이 없는 않은 경우에 BSS 영역에 할당
- 초기화: 프로그램 시작 시, 전역 공간에서 초기화 (단, const의 경우 클래스 선언 내에서 가능)
- 객체의 이름이나 클래스 이름으로도 접근이 가능
초기화시 주의할 점
일반 정적 멤버 변수를 초기화 할 때, 클래스 선언 내에서 초기화를 하면 안됩니다.
왜냐하면, 단일 정의 규칙 (ODR)에 위배될 수 있기 때문입니다.
클래스 정의는 헤더 파일에 있을 수 있으며, 여러 소스 파일에서 포함될 수 있습니다.
만약 클래스 내에서 static 멤버 변수를 초기화하면, 해당 헤더 파일을 포함하는 각 소스 파일마다 static 멤버의 정의가 중복되므로 링크 단계에서 오류가 발생합니다.
따라서 초기화는 소스 파일 내의 전역 공간에서 초기화 해야 합니다.
(같은 이유로 헤더 파일에서 정의할 수 없습니다.)
1
2
3
4
5
6
#pragma once
class Test
{
public:
static int a = 1; //오류
};
1
2
// cpp 파일의 전역 공간에서 초기화 해야 한다.
int Test::a = 1;
main()함수에서 초기화 할 수 없는 이유는 main() 함수도 함수 내이기 때문입니다.
정적 멤버 변수의 경우에는 모든 객체에서 공유되어야 하고, 때문에 모든 외부 파일에서 공유되어야 하기 때문에 외부 링크 정적 변수(External Linkage Static Variables)를 가집니다.
하지만 함수 안은 링크가 없는 정적 변수(No Linkage Static Variables) 범위입니다.
즉, 외부 링크를 가지는 전역 공간에서 초기화 해야 합니다.
static const
위에서 클래스 선언 내에서 초기화를 하면 안된다고 했지만, 예외가 있습니다.
바로 static const 멤버 변수의 경우입니다. (C++11 이후)
1
2
3
4
5
6
#pragma once
class Test
{
public:
const static int a = 1; //가능
};
이것이 가능한 이유는 const
의 특성 때문입니다.
const
는 한번 초기화 한 이후 값을 변경하는 것이 불가능하고, 때문에 컴파일 타임에 값이 결정됩니다.
이러한 경우에는 class 선언 내에서 초기화가 가능합니다.