C++의 저장 클래스

안녕하세요, 열정적인 프로그래머 여러분! 오늘 우리는 C++ 저장 클래스의 세계를 함께 탐험해보겠습니다. 프로그래밍 초보자라도 걱정하지 마세요; 친절한 안내자로서 저가 단계별로 설명해드릴 테니까요. 시작해보겠습니다!

C++ Storage Classes

저장 클래스는 무엇인가요?

구체적인 내용에 들어가기 전에, 저장 클래스가 무엇인지 이해해보겠습니다. C++에서 저장 클래스는 변수와 함수의 범위(가시성)와 수명을 정의합니다. 그들은 컴파일러에게 변수를 어떻게 저장해야 하고, 다른 파일에서 접근할 수 있는지, 그리고 메모리에 얼마나 오래 존재해야 하는지를 알립니다.

이제 각 저장 클래스를 자세히 탐구해보겠습니다.

auto 저장 클래스

C++의 auto 키워드는 시간이 지남에 따라 의미가 달라졌습니다. 최신 C++(C++11 이후)에서는 타입 추론에 사용됩니다. 그러나 구 버전에서는 저장 클래스 지시자로 사용되었습니다.

구 사용법 (C++11 이전):

int main() {
auto int x = 5;  // int x = 5;와 동일
return 0;
}

이 구 사용법에서 auto는 자동 저장 기간을 가진 변수를 명시적으로 선언합니다. 그러나 이는 로컬 변수의 기본값이었기 때문에 거의 사용되지 않았습니다.

최신 사용법 (C++11 이후):

int main() {
auto x = 5;  // x는 int로 추론됨
auto y = 3.14;  // y는 double로 추론됨
auto z = "Hello";  // z는 const char*로 추론됨
return 0;
}

최신 C++에서 auto는 초기화자에 기반하여 변수의 타입을 컴파일러가 추론하게 합니다. 복잡한 타입이나 타입이 미래에 변할 수 있는 경우에 특히 유용합니다.

register 저장 클래스

register 키워드는 이 변수가 자주 사용될 것이며 더 빠른 접근을 위해 CPU 레지스터에 유지되어야 한다는 힌트를 컴파일러에게 줍니다.

#include <iostream>

int main() {
register int counter = 0;

for(int i = 0; i < 1000000; i++) {
counter++;
}

std::cout << "Counter: " << counter << std::endl;
return 0;
}

이 예제에서 우리는 counter를 레지스터에 유지해야 한다고 컴파일러에게 제안하고 있습니다. 그러나 현대 컴파일러는 이러한 최적화를 자동으로 수행하기 때문에 register는 거의 사용되지 않습니다.

static 저장 클래스

static 키워드는 사용된 곳에 따라 다른 의미를 가집니다:

1. 정적 로컬 변수

#include <iostream>

void countCalls() {
static int calls = 0;
calls++;
std::cout << "This function has been called " << calls << " times." << std::endl;
}

int main() {
for(int i = 0; i < 5; i++) {
countCalls();
}
return 0;
}

이 예제에서 calls는 초기화된 후 값을 유지하며, 함수 호출 사이에 그 값을 유지합니다. 출력은 다음과 같습니다:

This function has been called 1 times.
This function has been called 2 times.
This function has been called 3 times.
This function has been called 4 times.
This function has been called 5 times.

2. 정적 클래스 멤버

class MyClass {
public:
static int objectCount;

MyClass() {
objectCount++;
}
};

int MyClass::objectCount = 0;

int main() {
MyClass obj1;
MyClass obj2;
MyClass obj3;

std::cout << "Number of objects created: " << MyClass::objectCount << std::endl;
return 0;
}

여기서 objectCountMyClass의 모든 인스턴스에서 공유됩니다. 출력은 다음과 같습니다:

Number of objects created: 3

extern 저장 클래스

extern 키워드는 다른 파일에 정의된 글로벌 변수나 함수를 선언합니다.

파일: globals.cpp

int globalVar = 10;

파일: main.cpp

#include <iostream>

extern int globalVar;  // globalVar의 선언

int main() {
std::cout << "Global variable value: " << globalVar << std::endl;
return 0;
}

이 예제에서 globalVarglobals.cpp에 정의되고 main.cpp에서 extern으로 선언되어 있습니다. 이렇게 하면 main.cpp가 다른 파일에서 정의된 변수를 사용할 수 있습니다.

mutable 저장 클래스

mutable 키워드는 const 객체의 멤버를 수정할 수 있도록 합니다.

class Person {
public:
Person(int age) : age(age), cacheValid(false) {}

int getAge() const {
if (!cacheValid) {
cachedAge = heavyComputation();
cacheValid = true;
}
return cachedAge;
}

private:
int age;
mutable int cachedAge;
mutable bool cacheValid;

int heavyComputation() const {
// 중한 계산을 시뮬레이션
return age;
}
};

int main() {
const Person p(30);
std::cout << p.getAge() << std::endl;  // 이는 허용됩니다
return 0;
}

이 예제에서 p는 const이지만, cachedAgecacheValidmutable로 지정되어 있기 때문에 수정할 수 있습니다.

요약

우리가 배운 저장 클래스를 요약한 표를 아래에 제공합니다:

저장 클래스 목적
auto 타입 추론 (최신 C++)
register 더 빠른 접근을 위한 힌트 (Rarely used)
static 함수 호출 사이에서 값을 유지하거나 클래스 인스턴스 간 공유
extern 다른 파일에서 정의된 변수나 함수를 선언
mutable const 객체의 멤버를 수정할 수 있게 하기

저장 클래스를 이해하는 것은 메모리를 효율적으로 관리하고 변수의 범위를 제어하는 데 필수적입니다. C++의 여정을 계속하면서 이 개념들이 자연스럽게 습득될 것입니다. 행복한 코딩을 기원합니다!

Credits: Image by storyset