Abseil Tip 109 함수 선언에서 의미 있는 const 사용

한글 번역


Tip of the Week #109: 함수 선언에서 의미 있는 const 사용

Greg Miller (jgm@google.com)
2016-01-14에 totw/109로 최초 게시

이 문서는 함수 선언에서 const가 언제 의미가 있고, 언제 의미가 없어 생략하는 것이 최선인지 설명합니다. 먼저, 선언(declaration)정의(definition)의 차이를 간단히 살펴보겠습니다.

다음 코드를 봅시다:

void F(int);                     // 1: F(int)의 선언
void F(const int);               // 2: F(int)의 재선언
void F(int) { /* ... */ }        // 3: F(int)의 정의
void F(const int) { /* ... */ }  // 4: 오류: F(int)의 재정의

1번과 2번은 함수 선언입니다. 함수 선언은 함수의 시그니처(signature)와 반환 타입을 컴파일러에 알려줍니다. 위 예제에서 함수의 시그니처는 F(int)입니다. 함수 매개변수 타입의 const 여부는 무시되므로 두 선언은 동일합니다. (참조: “Overloadable declarations”)

3번과 4번은 함수 정의입니다. 함수 정의는 함수의 본문도 포함하기 때문에 선언의 역할도 합니다. 따라서 3번은 F(int) 시그니처를 가진 함수의 정의입니다. 마찬가지로 4번도 동일한 함수의 정의이므로 링크 단계에서 오류가 발생합니다. 여러 번 선언은 가능하지만 정의는 한 번만 허용됩니다.

3번과 4번의 정의는 같은 함수를 선언하고 정의하지만, 선언 방식에 따라 함수 본문 내에서 차이가 있습니다. 3번 정의에서 함수 매개변수는 int(비-const) 타입이고, 4번 정의에서는 매개변수가 const int 타입입니다.


함수 선언에서 의미 있는 const

모든 const가 함수 선언에서 무시되는 것은 아닙니다. C++ 표준의 “Overloadable declarations”([over.load])에는 다음과 같이 나와 있습니다(강조 추가):

“매개변수 타입 명세 내에 포함된 const 타입 지정자는 중요하며, 오버로드된 함수 선언을 구분하는 데 사용할 수 있습니다.”

다음은 const가 중요하며 무시되지 않는 예제입니다:

void F(const int* x);                  // 1
void F(const int& x);                  // 2
void F(std::unique_ptr<const int> x);  // 3
void F(int* x);                        // 4

위 예제에서 매개변수 x 자체가 const로 선언된 것은 아닙니다. 각 함수는 x의 서로 다른 타입을 받아 유효한 오버로드 집합을 형성합니다.

  • 1번은 “포인터가 가리키는 값이 const int인 함수”를 선언합니다.
  • 2번은 “const int에 대한 참조를 매개변수로 받는 함수”입니다.
  • 3번은 “const int를 가리키는 unique_ptr을 매개변수로 받는 함수”입니다.

이러한 경우 const는 타입 명세의 일부로 간주되며, 매개변수 x 자체의 최상위(top-level) const 여부와는 다릅니다.

다음은 const가 의미 없고 무시되는 예제입니다:

void F(const int x);          // 1: F(int) 선언
void F(int* const x);         // 2: F(int*) 선언
void F(const int* const x);   // 3: F(const int*) 선언

간단한 규칙

C++의 복잡한 규칙을 완벽히 숙지하기는 어렵지만, 가능한 한 규칙을 이해하여 다른 C++ 프로그래머와 협업할 수 있는 코드를 작성하는 것이 중요합니다. 이를 위해 함수 선언에서 const의 의미와 무시되는 경우를 알아야 합니다.

아래는 하나의 합리적인 지침입니다:

  1. 정의가 아닌 함수 선언에서는 최상위 const를 사용하지 마세요.
    • 컴파일러에 의해 무시되며, 불필요한 시각적 잡음이 될 수 있고, 독자를 혼란스럽게 만들 수 있습니다.
    • 특히 무의미한 const를 복사/붙여넣기하지 않도록 주의하세요.
  2. 함수 정의에서는 최상위 const를 선택적으로 사용하세요.
    • 함수 내 로컬 변수를 const로 선언할 때와 동일한 기준을 적용할 수 있습니다.