static 그리고 const 키워드

Junhyeok Yun·2022년 10월 7일
1

C++

목록 보기
2/5
post-thumbnail

오늘의 목표

오늘은 static, const 키워드에 대해서 정확한 의미, 그리고 언제 사용해야 하는지 알아볼 것이다.


키워드와 식별자

먼저 키워드란 무엇인지, 그리고 식별자는 무엇인지 짚고 넘어가자.

키워드(keyword) : 컴퓨터 프로그래밍 언어에서 이미 문법적인 용도로 사용되고 있기 때문에 식별자로 사용할 수 없는 단어로 예약어(reserved word) 라고도 한다. 다음은 C++17 기준, 84개의 키워드다.

식별자(identifier) : C++에서 변수, 함수, 타입 또는 다른 종류의 객체의 이름이다. 다음은 C++에서 식별자의 이름을 지정할 때 따라야 하는 규칙이다.

  • 키워드는 식별자가 될 수 없다.
  • 식별자는 로마자 대문자와 소문자, 숫자, 밑줄 문자(_)로만 구성될 수 있다.
  • 식별자는 숫자로 시작할 수 없다.
  • 대문자와 소문자를 구별한다. (lowercase, lowerCase, LowerCase 모두 다 다른 식별자)

static 키워드란

C 프로그래밍 언어와 C++, 오브젝티브-C에서 static 은 정적 변수로서의 수명과 연계에 따라 달라지는 가시성을 모두 제어하는 예약어이다.

C++에서 static 은 예약어인 extern, auto, register 와 함께 기억 영역 분류(storage class) 지시자에 해당한다.
(더 이상 auto 키워드는 기억 영역 분류 지시자가 아니며 register 키워드는 C++에서 지원되지 않는다.)

기억 영역 분류(storage class)란 변수와 함수의 생명 주기(life time)와 가시성의 범위(scope)를 정의하는 것을 말한다. 모든 변수와 기능은 이러한 기억 영역 분류 가운데 하나를 가지고 있으며 선언에서 기억 영역 분류를 지정하지 않으면 상황에 따라 문맥 의존 default가 사용된다.

static 으로 선언된 변수는 프로그램 실행동안 값을 유지한다는 점에서 전역 변수와 동일하지만 사용범위가 제한 된다는 점에서 전역변수와 다르다.

전역 변수를 static 으로 선언하면 사용범위가 선언된 파일로 한정되어 다른 파일에서는 접근이 불가능하다.

지역 변수를 static 으로 선언하면 선언된 해당 함수내에서만 사용이 가능한 지역 변수의 특성과 프로그램 실행동안 값을 유지하는 전역 변수의 특성을 모두 가지고 있다.

C++에서의 static 활용

  • 전역 변수나 전역 함수를 클래스에 캡슐화
    static 키워드는 위에서 서술한 지역 변수로 선언했을 때 해당 함수 내에서만 사용이 가능하고 프로그램 실행동안 값을 유지하는 특성을 활용하여 클래스에 static 멤버를 작성하여 전역 변수나 전역 함수의 기능이 필요할 때 캡슐화할 수 있다.
	class Compare {
	public:
		...
		static int max(int a, int b) { return (a>b) ? a : b; }
    	...
	};

	int main() {
		...
    	cout << Compare::max(36, 94) << endl;
	    ...
	}
  • 객체 사이에 공유 변수를 만들고자 할 때
    클래스의 static 멤버는 객체가 생기기 전에 이미 생성되어 있고 객체가 사라져도 소멸되지 않으며 클래스 당 하나면 생기고 모든 객체들이 공유한다. 따라서 모든 객체들이 공유해야 하는 공유 멤버는 static 키워드로 선언해야 한다.
	class Team {
		...
		static int sharedMoney; // 공금을 나타내는 변수
    	...
	};

	// static 멤버 변수는 외부에 전역 변수로 선언되지 않으면 링크 오류 발생
	int Team::sharedMoney = 100000;  

const 키워드란

When it modifies a data declaration, the const keyword specifies that the object or variable isn't modifiable.
-- "이것이 데이터 선언문을 수식할 때, const 키워드는 객체 또는 변수가 수정될 수 없음을 명시한다." --

const 키워드는 변수의 값이 상수임을 명시하고 컴파일러에게 프로그래머가 이것을 수정하는 것을 방지하도록 한다.

C++에서는 #define 전처리기 구문 대신 상수를 정의하는 데 const 키워드를 사용할 수 있으며, 이 때 const 키워드로 선언된 값은 type checking의 대상이 된다.

C에서 상수 값은 기본적으로 external linkage로 설정되어 있지만 C++에서 상수 값은 기본적으로 internal linkage로 설정되어 있다.

C++에서의 const 사용

  • 배열 길이에 의미 부여
	const int maxarray = 255;
	char store_char[maxarray]; // C에서는 허용되지 않음
  • (타입)에 대한 상수형 포인터 선언
    char* const 로 선언된 포인터는 변수의 값은 바꿀 수 있지만 가리키는 주소값을 바꿀 수는 없다.
   char this_char{'a'}, that_char{'b'};
   char* mybuf = &this_char, *yourbuf = &that_char;
   char* const aptr = mybuf;
   *aptr = 'c';   // OK
   aptr = yourbuf;   // C3892 컴파일 에러 ('var' : you cannot assign 
   					 // to a variable that is const)
  • 상수형 (타입)에 대한 포인터 선언
    const char* 로 선언된 포인터는 가리키는 주소값은 바꿀 수 있지만 (똑같이 const char* 로 선언된 포인터여야 함) 변수의 값을 바꿀 수는 없다.
    함수가 포인터를 통해 매개변수를 변경하지 못하도록 매개변수에 const char* 로 선언된 포인터를 사용하기도 한다.
   const char* mybuf = "test";
   const char* bptr = mybuf;   // Pointer to constant data
   *bptr = 'a';   			   // Error
}
  • 상수형 (타입)에 대한 상수형 포인터 선언
    const char const*로 선언된 포인터는 가리키는 주소값과 변수의 값 모두 바꿀 수 없다.
	const char const* mybuf = "test";
    const char const* yourbuf = mybuf; // Error
    *mybuf = 'a'; // Error
  • 상수 객체 (constant objects)
    const 로 선언된 객체들은 상수 객체 (constant objects) 라고 부르며, 컴파일러는 constant objects가 절대 변경되지 않도록 보장한다.
    constant objects는 오직 상수 멤버 함수(constant member functions)만 호출할 수 있지만, non-constant objects는 constant member functions와 non-constant member functions 모두 호출할 수 있다.
    const 키워드를 사용하여 함수 중복(overload)을 할 수 있다. 이렇게 하면 constant objects와 non-constant object가 각각 다른 버전의 함수를 호출할 수 있게 된다.
    생성자와 소멸자를 const 키워드로 선언할 수 없다.

  • 상수 멤버 함수(constant member functions) 선언
    const 키워드로 멤버 함수를 선언하면 객체를 수정하지 않는, 즉 읽기 전용 함수임을 명시하는 것이다. constant member function은 non-static data member를 수정할 수 없고 non-constant member function을 호출할 수 없다.
    constant member function을 선언하기 위해서는, const 키워드를 매개 변수 괄호 뒤에 작성하면 된다. const 키워드는 함수 선언과 정의에 둘 다 작성해줘야 한다.

// constant_member_function.cpp
class Date
{
public:
   Date( int mn, int dy, int yr );
   int getMonth() const;     // A read-only function
   void setMonth( int mn );   // A write function; can't be const
private:
   int month;
};

int Date::getMonth() const
{
   return month;        // Doesn't modify anything
}
void Date::setMonth( int mn )
{
   month = mn;          // Modifies data member
}
int main()
{
   Date MyDate( 7, 4, 1998 );
   const Date BirthDate( 1, 18, 1953 );
   MyDate.setMonth( 4 );    // Okay
   BirthDate.getMonth();    // Okay
   BirthDate.setMonth( 4 ); // C2662 Error
}

참고자료

profile
개발 공부 일지

0개의 댓글