[C/C++]C++의 키워드 몇 가지

2022. 4. 9. 00:12Programming language/C, C++

    목차

이 글은 이전에 운영하던 깃 블로그에서 옮겨온 글입니다.

 

서론

C++을 공부하면서 사용해본 혹은 찾아본 예약어를 몇 가지 적어보고자 합니다. 이것도 은근히 기술면접 질문으로 많이 나온다고 합니다. 무의식적으로 아 그런 기능인가 보다 하고 사용하다가, 어? 이런 거야?라고 깨닫게 되는 순간들이 문득 있었던 추억이 있습니다. 익숙한 게 무섭다는 게 이런 걸까요?


const / constexpr

상수 객체를 만들 때 많이 사용했던 키워드들입니다. 두 가지가 있는데 둘 모두, 객체를 상수화 시킵니다.

그런데 굳이 두 가지가 따로 있다는 건, 차이가 있다는 것이겠죠. 어떤 차이가 있을까요?

 

const

  • 컴파일 타임, 런타임에 초기화될 수 있음
  • 비 정적 멤버 함수에만 쓸 수 있다
    => 이 경우 const 멤버 함수는 비 정적 멤버 변수의 값을 변경하지 않는다는 것을 보장

constexpr

  • 정수로 계산될 수 있는 부분은 컴파일 시간에 계산되도록 할 때 주로 사용
  • 비 정적 멤버 함수, 생성자에도 사용 가능. virtual(가삼 함수)이 아니여야 함
  • constexpr로 선언된 함수의 파라미터는 모두 리터럴 타입 이거나 리터럴 타임의 참조 형이어야 함
  • constexpr로 선언된 함수는 본체가 컴파일러에 노출되어야 함(치환되기 때문)
    => 선언과 동시에 정의가 되어 있어야 함과 같은 말

처음 이 두 키워드를 봤을 때는 "도대체 무슨 차이지? 상수화는 똑같잖아."라는 의문을 가졌습니다. 하지만 차이는 있었습니다. 위 설명을 보면 가장 큰 차이는 '컴파일 타임에만 사용 가능한지 여부'입니다.

 

const의 경우 컴파일 / 런타임 모두 초기화 가능하지만, constexpr는 컴파일 때만 가능합니다.
뭐… 사실 별 상관없어 보일 수 있네요. 저는 C++ 코딩을 했을 때 constexpr를 주로 사용했었습니다.


mutable

상 수화된 멤버는 변경이 불가능하다? 아닙니다. 상 수화된 멤버 함수에서 멤버 변수를 변경할 수 있도록 해주는 키워드가 존재합니다. 바로 mutable입니다. 직역하자면 "변하기 쉬운" 이라는데, 어떤 특징을 가진 키워드일까요?

 

mutable은 const 함수에서 mutalbe로 선언된 비 정적 멤버 변수는 수정 가능하게 해 줍니다. 여기서 중요한 건, 비 정적 멤버 변수여야 한다는 겁니다. 보통 상 수화된 멤버 함수나 상수 객체는 값을 변경하지 않습니다. 하지만 특정 값만을 제외하고 싶은 경우가 있는데 이때 해당 변수만 mutable로 선언한다면 상 수화된 멤버 함수나 상수 객체도 값을 변경하는 현상을 즐길 수 있을 겁니다.


explicit

묵시적인 타입 변환을 하지 않고 명시적인 타입 변환을 했을 경우만을 허용한다는 키워드입니다. 가끔 원하지 않는 타입 변환이 일어났을 경우가 있는데, 이때 발생하는 에러를 발생시키기 때문에 이로 인한 문제를 사전에 방지할 수 있습니다.

 

객체 생성 관계를 명확하게 하고자 할 때 주로 사용되며, 간혹 실수로 잘못된 값을 넣어줬는데 잘되는 경우가 발생합니다.

 

프로그래밍을 하다 보면 타입 변환 시 안 되는 경우도 있지만, "어? 왜 되지?" 같은 경우가 생기기도 합니다. 이는 묵시적인 타입 변환이 일어나기 때문입니다. 이 키워드는 그런 현상을 줄여줍니다. 막는다기 보다는 '줄여'줍니다.


export

template를 선언과 정의를 분리할 수 있도록 도와주는 키워드입니다. 이 키워드는 다음과 같은 특징과 제한사항을 가집니다.

  • 템플릿의 정의를 외부에 알림
  • 템플릿이 인스턴스화 된 것과 정의가 된곳 모두 인스턴스화 과정 처리가 되어야 함
    => 정의를 포함한 파일을 수정할 경우, 해당 템플릿을 사용하는 모든 파일을 다시 컴파일해야 한다
  • 분리 모델 : export 키워드를 이용하여 명시적 인스턴스 화가 아니더라도 선언과 구현을 서로 다른 번역 단위에서 작성할 수 있도록 하자는 것

 


volatile

해당 키워드가 붙은 변수는 최적화를 진행하지 않습니다. 프로그래밍을 공부하면서 종종 듣던 말이 있습니다.

컴파일러는 우리를 속이지 않는다. 잘못된 결과가 나오면 프로그래밍이 잘못된 탓이다.

맞는 말이라고 쭉 생각하다, 멀티 스레드 프로그래밍을 할 때 보고 말았습니다. 컴파일러도 우리를 기만했었습니다. 분명 최적화된 값이 나오면 안 되는 상황인데(멀티 스레드 프로그래밍을 하다 보면, 종종 발생하는 데이터 접근 우선순위와 동기화 문제...) 자세하게는 다루지 않겠습니다. 어려운 내용이기도 하고, 너무 길어지니... 다시 본론으로 돌아가 키워드에 대한 설명을 계속하겠습니다.

 

  • 레지스터에 volatile 변수의 값이 캐시 되지 않게 하여 메모리에서 바로 값을 읽도록 함
  • CPU 내의 캐시는 활용함
  • 외부 요인에 의하여 값이 변경될 가능성이 있는 변수들에 주로 사용됨
    => 멀티 스레드 프로그래밍, Memory mapped I/O, 시스템 시간 등

말이 이상하지만, 최적화를 하지 말아야 하는 경우(최적화되지 않는 상황에서 디버깅해야 하는 경우 등) 이 키워드를 써주도록 하자. 사실... 최적화라고 무조건 좋은 것만은 아닐 수 있다는 걸 알게 된 건 신선한 충격이었습니다.


register

해당 키워드로 선언된 변수는 메모리에 저장되는 것이 아닌 레지스터에 직접 저장되게 해 줍니다.

  • 실제로 연산에 사용되는 레지스터에 저장하기에 연산 시간을 줄임(메모리에서 읽어오는 시간 절약)
  • 해당 변수가 굳이 메모리에 기록될 필요가 없을 경우 레지스터에 저장되도록 권유하는 역할
  • 최근 컴파일러들은 레지스터에 저장될 수 있다면 알아서 최적화를 해주기 때문에
    무시되거나 잘 사용되지 않는다고 함

auto

이 키워드는 가장 많이 썼던 거 같습니다. 변수 초기화 값에 의거하여 변수의 타입을 추론하는 키워드입니다.

  • 변수 정의 때 명시적인 타입을 정하지 않아도 됨
  • 값에 상응하는 타입을 추론시켜주는 키워드
  • 컴파일 때 타입이 결정

정말 많이 썼던 거 같아요. 간혹 자료형들보다 이 키워드를 먼저 배우는 경우가 있는데, 자료형을 선언하거나 타입을 명시해주는 게 익숙하지 않은 경우(처음 공부하는 경우)는 이 키워드를 안 쓰는 연습도 해보는 게 좋을 거 같습니다. 물론 요즘에는 마우스 포인터만 가져가면, 형을 알 수 있지만 뭐… 귀찮으니까요. 그런데 이 키워드로 코딩 시간이 약간이나마 줄었던 거 같습니다.

 


decltype

주어진 표현식의 타입을 컴파일러가 직접 추론해서 결정하라고 지시하는 키워드입니다.

  • 주로 함수의 반환 타입 결정에 사용
  • 주어진 표현식의 타입을 알려주는 키워드
  • 값으로부터 타입을 추론해 낼 수 있는 키워드

= default

컴파일러가 함수를 자동으로 생성하도록 명시적으로 지정

 


= delete

컴파일러가 함수를 자동으로 생성하지 못하도록 명시적으로 지정


override

  • 오버 라이딩된 멤버 함수 뒤에 삽입하여, 해당 함수가 오버 라이딩된 함수라는 것을 명시
  • 오버 라이딩된 멤버 함수가, 원본 함수와 형태가 다를 경우 문법 오류를 발생시켜 오류를 사전 방지

여담이지만, C#을 하면서는 이 키워드를 필수로 써줘야 했던 거 같습니다. 문법적으로 필수로 명시를 한다는 뜻입니다.


extern

이 키워드로 선언된 전역 변수는 이미 다른 파일에 선언되어있는 변수라는 것을 알려주는 녀석입니다.

DLL 같은 라이브러리를 만들 때 주로 사용했던 것 같습니다.


inline

인라인 함수로 만들어주는 키워드입니다.

  • 인라인 함수는 전처리 과정에서 코드를 직접 삽입하여 줌 (매크로 함수와 비슷)
  • 일반 함수처럼 정의할 수 있기 때문에 매크로 함수에 비하여 복잡한 정의와 자료형 검사를 함
  • 인라인 함수는 최상단이나 헤더 파일에 만드는 것이 일반적
  • 함수 포인터를 사용하는 경우나, 가상 함수, 재귀 함수에는 사용할 수 없음

마무리

많은 키워드를 소개해 봤지만, 실제로 많이 썼던 것도 있는가 하면 그렇지 않은 것도 있는 거 같습니다. 각 상황에 맞게 필요에 의해 찾아서 썼던 키워드들도 종종 있네요. 프로그래밍을 공부할 때 간단하게 어떤 키워드다 이런 상황에 쓴다라고 외워서 사용하는 경우들이 종종 있는데, 항상 왜 사용하는지와 어떤 제약이 있으며 대체제가 무엇이 있는지 등 생각하는 게 중요한 것 같습니다.

반응형
LIST