1.2 컴파일

SeungHee Yun·2023년 7월 20일
0

전문가를 위한 C++

목록 보기
2/15

개요

앞선 포스트에서 빌드의 7번째 단계 후, 각 코드 별로 해석 유닛( TU )를 생성한다고 했습니다.
물론, 이 TU가 생성이 되기 위해선, 흔히 생각하는 C++상에서의 문법 오류가 없어야 합니다.

하지만 우리가 잘 인지하지 못하는 TU에 적용되는 중요한 규칙이 있습니다.

바로 각 TU에 존재하는 모든 변수, 함수, 클래스, enum,
템플릿 등등의 정의( Definition )은 유일
해야하고,
inline이 아닌 모든 함수의 변수들의 정의는 전체 프로그램에서 유일해야 한다.라는
유일 정의 규칙( One Definition Rule - ODR ) 입니다.

그럼 C++에서 이야기 하는 정의 란 무엇일까요?


정의( Definition )와 선언( Declaration )

우리는 종종 정의와 선언을 혼동해서 사용하곤 합니다.
하지만 C++에서 이 둘은 엄연히 다른 개념입니다.

먼저 선언( Declaration )이란 TU에 새로운 이름을 도입하거나,
기존에 선언된 이름을 재선언 하는 것입니다.

예를 들어

int f();

의 경우, f 라는 함수를 선언했습니다.

그리고 정의는 선언을 포함하는 개념으로, 선언된 개체를 완전히 정의함을 뜻합니다.

예를 들어,

int a;

의 경우 a 라는 `int 변수를 정의한 것입니다.

하지만 extern 지정자가 들어간 선언의 경우 명시적으로 초기화 되지 않는다면 선언입니다.

extern const int a;             // a를 선언하였지만 정의하지 않음
extern const int b = 1;         // b를 정의함

위의 경우는, a는 선언, b는 정의 입니다.

또한, 클래스 정의 내부에 inline이 아닌 static 멤버의 경우 정의입니다.

struct S {
    int n ;                         // S::n 정의
    static int i;                   // S::i를 선언하지만 정의는 아님
    inline static int x;            // S::x 를 정의
};                                  // S를 정의
int S::i;                           // S::i를 정의

유일 정의 규칙( One Definition Rule )

각 TU에 존재하는 모든 변수, 함수, 클래스, enum, 템플릿 등등의 정의( Definition )는
유일해야 하고, inline 이 아닌 모든 함수의 변수들의 정의는
전체 프로그램에서 유일해야 한다.

이 말은 즉, TU안에 같은 선언은 여러개 있어도 괜찮다는 의미 입니다. 실제로

int f();        // f 의 선언
int f();        // f 의 선언
int f();        // f 의 선언

위 코드는 문제가 없습니다. 왜냐하면, int f()f 의 선언이지
정의가 아니기 때문입니다. 하지만

int f() 
{
    return 0;
}
int f() 
{
    return 0;
}

위와 같은 경우 컴파일을 하였다면, 다음과 같은 오류가 발생하게 됩니다.

test.cc:5:5: error: redefinition of ‘int f()5 | int f() {
  |     ^
test.cc:1:5: note:int f()’ previously defined here
1 | int f() {
  |     ^

또 ODR이 내포하는 다른 뜻은,
inline이 아닌 모든 함수의 변수들의 정의는 전체 프로그램에서 유일해야한다.

즉, inline 으로 정의되지 않는 모든 함수들과 변수들의 경우 프로그램을 구성하는 모든 TU에 정의가 단 하나 있어야합니다.

inline 키워드의 의미

원래 inline 키워드가 처음 도입되었을 때의 의미는, 컴파일러에게
이 함수를 호출하는 문장을 그냥 이 함수의 내용으로 치환시켜도 된다 라는 의미였습니다.

하지만 현대의 C++컴파일러는 굉장히 똑똑해졌기 때문에,

우리가 굳이 inline이라고 명시하지 않아도
만일 인라인하는 것이 효율이 좋다면 인라인을 시키고,

반대로 인라인 함수가 인라인을 안했을 때, 효율이 좋다면 인라인화를 하지 않습니다.
따라서 현대의 `inline 키워드는 다음과 같은 의미를 나타낸다고 보시는게 낫습니다.

이 함수는 여러개의 TU에 정의되어 있어도 괜찮음!!


참조 : 모두의 코드 : 씹어먹는 C++


profile
Enthusiastic Game Developer

1개의 댓글

comment-user-thumbnail
2023년 7월 20일

글이 잘 정리되어 있네요. 감사합니다.

답글 달기