#1. 개념
1. static 키워드
static 키워드는 변수 혹은 함수를 내부 링킹을 통해 정의하기 위해 사용됩니다. 더불어, static으로 정의한 변수 혹은 함수는 메모리 구조의 Data 영역에 저장되어 프로그램의 시작과 함께 메모리가 할당되며, 프로그램의 종료 시점에 해제됩니다. static 키워드는 어떤 함수 내 static 변수, 어떤 클래스 내 static 데이터 멤버, 그리고 static 멤버 메서드에 사용됩니다.
2. 링킹
C++ 환경에서 소스 파일이 컴파일 되면 목적 파일이 생성됩니다. 그리고, 서로 다른 목적 파일들을 '링킹' 단계에서 하나로 묶어 주어 하나의 실행 파일이 생성됩니다. 이때, 변수나 함수의 이름을 기준으로 목적 파일 안에서 일어나는 변수 참조 혹은 함수 호출 등이 서로 연결되는데 같은 소스 파일 안에서 일어나는 작업을 내부 링킹, 서로 다른 소스 파일 간 연결 작업을 외부 링킹이라고 합니다.
3. 내부 링킹 vs 외부 링킹
1. 내부 링킹
내부 링킹은 같은 소스 파일 혹은 번역 단위 내에서 함수, 변수 등을 해결하는 작업을 의미합니다. 같은 번역 단위 내 변수 참조 혹은 함수 호출등의 연결 작업을 수행합니다.
2. 외부 링킹
외부 링킹은 서로 다른 소스 파일 혹은 번여 단위(라이브러리 등)에서 정의된 변수 참조 혹은 함수 호출 작업등을 연결하는 작업입니다.
4. 내부 링킹 코드
// AnotherFile.cpp
#include <iostream>
using namespace std;
void f(); // 일반 선언
void f()
{
cout << "f is called'\n'" << endl;
}
static void f2(); // static 선언
void f2()
{
cout << "f2 is called'\n'" << endl;
}
/***********************************************/
// FirstFile.cpp
void f();
int main()
{
f(); // Ok!!
f2(); // Error!!
return;
}
Details
- 위 코드에서 "f()" 함수 호출은 아무런 문제가 없습니다,
- 왜냐하면 "FirstFile.cpp"에서 호출하는 "f()" 함수는 외부 링크를 통해 다른 소스파일에서 찾기 때문입니다.
- 반면에, "f2()" 함수의 호출은 문제가 발생합니다.
- 함수의 프로토타입 선언 시 "static" 키워드를 통해 내부 링킹을 강제했기 때문입니다.
- 따라서, "AnotherFile.cpp"에 선언한 "f2()" 함수의 프로토타입을 "FirstFile.cpp"에서는 찾을 수 없게됩니다.
5. 외부 링킹 코드
extern int x;
int x = 3;
Details
- "extern" 키워드는 "static"과 반대로 명시적으로 외부 링킹 할 대상을 선언합니다.
- "extern" 키워드는 전역 변수보다 더 넓은 접근성을 제공하고, 정의된 변수를 참조하는 외부 파일에서 유용하게 사용됩니다,
- 왜냐하면 "extern" 키워드는 모든 소스파일에서 전역적으로 변수에 접근할 수 있도록 해주기 때문입니다.
#2. 클래스의 static 키워드
1. 개념
- static 데이터 멤버 : static 데이터 멤버의 경우, 객체별로 따로 존재하지 않고, 모든 객체에 공통으로 속하는 하나의 데이터만 존재합니다. 예를 들면, Animal 클래스를 통해 생성한 원숭이 객체와 펭귄 객체는 각각 운동 능력, 먹는 음식 등 다양한 속성 등을 별도로 수정 가능하지만, 동물인지, 혹은 사람인지에 대한 여부는 클래스 수준에서 static 데이터 멤버를 통해 공통으로 속하는 단 하나의 데이터 멤버로 존재합니다
- static 멤버 함수: 특정 객체에 종속되어 호출되지 않고, 클래스 수준에서 존재합니다.
2. staitc 데이터 멤버의 초기화
class Locator
{
public:
static void Register(Interface* _service) { service = _service; }
static Interface* Provide() { return service; }
private:
static Interface* service;
};
// static 데이터 멤버는 외부에서 초기화 해주어야 에러가 발생하지 않습니다!
Interface* Locator::service = nullptr;
Details
- static 데이터 멤버는 동일한 파일 유효 범위 내 클래스 정의 밖에서 초기화해주어야 그 효율성을 가집니다. 왜냐하면, 생성자에서 static 데이터 멤버를 초기화 할 경우, 해당 클래스 객체들은 클래스의 데이터 멤버들의 복사본을 가지며, 각 객체의 생성 시점에 생성자가 매번 호출되기 때문이죠.
#3. namespace
1. static의 대안 namespace
#include <iostream>
using namespace std;
namespace {
void F2();
void F2()
{
cout << "F2 is called\n" << endl;
}
}
Details
- "static" 키워드 사용의 대안으로 무명 네임스페이스(namespace) 사용을 고려해볼 수 있습니다.
- 네임스페이스 블록 안에 있는 코드는 내부 링킹이 강제되어 같은 소스파일의 코드는 서로 이용 가능하지만,
- 외부 소스 파일에서는 접근할 수 없습니다.
'언어 > Basic C++' 카테고리의 다른 글
[Basic C++] #29_Set, STL 컨테이너 (0) | 2022.11.19 |
---|---|
[Basic C++] #22_참조형 변수 (0) | 2022.10.12 |
[Basic C++] #61_객체 풀, Obejct Pooling (0) | 2022.10.07 |
[Basic C++] #60_스마트 포인터 (0) | 2022.09.28 |
[Basic C++] #59_가비지 컬렉션 (1) | 2022.09.27 |