BOBO's Note

static 키워드 본문

C, C++

static 키워드

bobo_hee 2020. 6. 4. 18:05

static 키워드는 어디에서 사용되는지에 따라 다양한 의미를 지닌다.

  1. 전역 변수에 붙는 staic 키워드
  2. 함수에 붙는 static 키워드
  3. 지역 변수에 붙는 static 키워드
  4. 클래스 멤버 변수에 붙는 static 키워드
  5. 클래스 멤버 함수에 붙는 static 키워드

각 경우에 대해서 살펴보기 앞서 identifier의 속성에 대해서 먼저 알아보자.

identifier의 속성

identifier는 변수, 함수, 타입, 객체 등의 이름이다. identifier에는 다음과 같이 세가지 속성이 존재한다.

  1. scope(스코프): 접근할 수 있는 위치를 결정한다.
    1. local scope(=block scope): 지역 변수, 함수의 매개변수는 선언된 블록 내에서만 접근할 수 있다.
    2. global scope(=file scope): 전역 변수, 함수는 소스 파일의 모든 위치에서 접근할 수 있다.
  2. duration(주기): 변수가 생성 및 소멸하는 시점을 결정한다.
    1. automatic duration: 지역 변수는 정의된 시점에 생성되어 정의된 블록이 끝나면 소멸한다.
    2. static duration: 전역 변수 및 static 지역 변수는 프로그램이 시작될 때 생성되어 프로그램이 종료될 때 소멸한다.
    3. dynamic duration: new, malloc으로 할당할 때 생성되어 delete, free로 해제할 때 소멸한다.
  3. linkage(링크): 동일한 이름의 여러 identifier가 존재할 때, 이를 참조할 수 있는 범위를 결정한다.
    1. no linkage: 지역 변수는 링크가 없다. 따라서 자신만을 참조한다.
    2. internal linkage: static 전역 변수, const 전역 변수, static 함수는 선언된 파일 내에서 어디서든 참조할 수 있다.
    3. external linkage: 함수, 전역 변수는 다른 파일에서도 참조할 수 있다.
      • extern 키워드를 붙여 다른 파일에 선언된 변수를 표시하여 링크 정보를 가져온다.

전역 변수에 붙는 static 키워드

일반적인 전역 변수는 기본적으로 extern linkage 속성을 갖는다. 즉, 외부 파일에서도 해당 변수를 참조할 수 있다.

전역 변수에 static 키워드를 붙이면 internal linkage 속성을 갖게 된다. 선언된 파일 내에서만 참조할 수 있고, 외부 파일에서는 참조할 수 없다.

static int a = 10; // available only in the current file

함수에 붙는 static 키워드

일반적인 함수도 전역 변수와 마찬가지로 extern linkage 속성을 기본 속성으로 갖는다. static 키워드를 통해 internal linkage로 설정해줄 수 있다.

// available only in the current file
static int add(int a, int b){
    return a + b;
}

지역 변수에 붙는 static 키워드

지역 변수는 auto duration을 갖는다. 즉, 선언된 블록 내에서만 유효한 생명주기를 갖는다.

static 키워드를 통해 static duration으로 설정해줄 수 있다. 다시 말하자면 프로그램 내내 존재하고, 해당 블록이 종료되더라도 값을 유지한다. 따라서 이후에 해당 블록에 재접근하면 이전에 갖던 값을 그대로 사용할 수 있다. static 지역 변수는 최초에 한 번만 초기화된다.

void count(){
    static int cnt = 0;

    cout << cnt++ << endl; // keep incrementing
}

 

클래스 멤버 변수에 붙는 static 키워드

static 멤버 변수는 동일한 클래스의 모든 객체가 공유한다. 즉, 해당 클래스에 하나만 생성된다. 따라서 static 멤버 변수는 클래스 변수라고도 불린다.

 

public으로 지정된 static 멤버 변수에 인스턴스를 통해 접근할 수도 있지만, 클래스명으로도 접근할 수 있다. 클래스명으로 접근할 수 있다는 것은 객체를 생성하지 않고도 곧바로 접근할 수 있다는 것을 의미한다.

 

클래스 내에서 초기화할 수 없기 때문에 전역 변수처럼 외부에서 초기화해야 한다.  heap이나 stack 영역이 아닌 data 영역에 생성된다. 따라서 프로그램이 시작되면서 메모리를 할당 받는다.

#include <iostream>

using namespace std;

class MyClass{
public:
    void print(){
        cout << cnt++ << endl;
    }
    static int cnt;
};

// initialize at outside of the class
int MyClass::cnt = 0;

int main(){
    MyClass instance = MyClass();
    instance.print();        // 0

    MyClass instance2 = MyClass();
    instance2.print();        // 1

    // can access by class name
    cout << MyClass::cnt;    // 2

    return 0;
}

 

클래스 멤버 함수에 붙는 static 키워드

static 멤버 함수는 static 멤버 변수와 마찬가지로 동일한 클래스의 모든 객체가 하나의 함수로 공유한다. 객체를 생성하지 않고도 클래스명으로 호출할 수 있다.

 

static 멤버 함수 내에서는 static 멤버 변수만 사용할 수 있고, this 포인터를 사용할 수 없다.

 

주로 private으로 지정된 static 멤버 변수에 접근하기 위해 사용된다.

#include <iostream>

using namespace std;

class MyClass{
public:
    static void print(){
        // (compile error) can't use non-static member variable
        // cout << a << endl;
        cout << cnt++ << endl;
    }
private:
    static int cnt;
    int a;
};

// initialize at outside of the class
int MyClass::cnt = 0;

int main(){
    MyClass instance = MyClass();
    instance.print();        // 0

    MyClass instance2 = MyClass();
    instance2.print();       // 1

    return 0;
}

'C, C++' 카테고리의 다른 글

연산자 오버로딩  (0) 2020.06.29
Reactive Programming  (0) 2020.06.13
Design Pattern  (0) 2020.06.04
Comments