글
중복 컴파일 방지를 위해 자주 쓰이는 전처리기 지시자들에 대해 비교해 보고자 한다.
1) #ifndef
먼저 다음과 같은 코드가 있다고 하자.
First.h
#ifndef _FIRST #define _FIRST class First { }; #endif
Second.h
#ifndef _SECOND #define _SECOND #include "First.h" class Second { }; #endif
Main.cpp
#include "First.h" #include "Second.h" void Main() { }
Main.cpp 를 컴파일 해보면 #include 의 작동방식에 따라
그 파일의 코드가 그대로 복사될 것이다.
#ifndef _FIRST #define _FIRST class First { }; #endif //////////////////////////////// #ifndef _SECOND #define _SECOND #include "First.h" class Second { }; #endif //////////////////////////////// void Main() { }
위와 같이 되고 Second 에서 또 한번 #include "First.h" 를 읽게 될 것이다.
그 결과로 ,
#ifndef _FIRST #define _FIRST class First { }; #endif //////////////////////////////// #ifndef _SECOND #define _SECOND #ifndef _FIRST #define _FIRST class First { }; #endif class Second { }; #endif //////////////////////////////// void Main() { }
위의 코드와 같이 Main.cpp 에는 First.h 이 2번 복사되는 결과를 볼 수 있다.
결론을 내리자면, #ifndef 의 방식으로 중복 컴파일을 피하는 것은
#include 명령어를 사용한 횟수 만큼 전처리기가 그 파일을 복사해오고,
복사해 온 코드 상단에 작성된 #ifndef 구문을 읽고 컴파일 여부를 확인 한다는 것이다.
이렇게 결론을 지으면
'그런데도 왜 이 방식을 써서 중복 컴파일 방지를 하냐 ?!'
라고 할 수 있다. 물론 장점도 존재하고 포스팅 마무리할 때쯤 언급하겠다.
2) #pragma once
그런데 나는 - pragma - 라는 단어가 대체 무슨 뜻인지 궁금해서 찾아보았다.
짜증. 괜히 맛있는 치킨만 먹고 싶어졌다.
그냥 컴파일러 지시자? 정도로만 이해해야겠다.
구글에 검색해도 pragma 가 뭐 하는 녀석인지만 나와있지,
정작 pragma 라는 단어 자체의 뜻에 대해서는 잘 안 나오는 듯_-_
어쨌든 잡소리였고 다시 중복 컴파일 방지를 위한 #pragma once 명령어로 돌아가자.
이 지시자가 의미하는 바는 '1번만 컴파일 하겠다' 라는 뜻으로 알고 있다.
msdn 에 따르면 (http://msdn.microsoft.com/en-us/library/4141z1cx(v=vs.80).aspx)
Pragma 지시자의 토큰 값으로 들어갈 수 있는 once 키워드 :
Specifies that the file will be included (opened) only once by the compiler when compiling a source code file.
Remark : This can reduce build times as the compiler will not open and read the file after the first #include of the module.
아까 말한 것과 다를 바 없고, 이게 전부다.
#ifndef 과 다르게 include 로 인해 여러 번 파일을 열어서 읽는 것이 아니라서 빌드 타임을 감소시킬 수 있다는 점.
3) 정리
#ifndef :
- 앞서 보았듯이 헤더 파일을 여러 번 include 하게 되면 define 여부를 계속 체크해야 되기 때문에
컴파일 단계 중에서 파일 해석 단계의 속도가 #pragma once 에 비해서 다소 느리다고 할 수 있다.
하지만 장점을 꼽자면 전처리기 지시자(Preprocessor directive)라서 모든 컴파일러에서 동작한다는 점이다.
#pragma once :
- 1번만 컴파일 하고 그 뒤로부터는 동일한 파일의 경우, 읽기조차 하지 않는다. 그래서 파일 해석 단계의 속도가
#ifndef 보다는 빠르다. 하지만 아까 사전적 의미를 찾아봤을 때, 자세히 보면 'A compiler directive' 라고 적혀있다.
컴파일러 지시자로 특정 컴파일러에서만 동작하는 지시자이며 Visual C++ 5.0 이상에서만 동작한다고 한다.
얼핏 속도면에서 보면 #pragma once 가 좋아보일 수 있으나
거대 프로젝트가 아닌 이상 속도에서 큰 차이를 볼 수 있을까? 하는 의문이 든다.
그리고 안정성(호환성)과 범용성을 고려한다면 #ifndef 방식을 택해야 할 것이다.
4) Reference
http://neodreamer-dev.tistory.com/310
http://msdn.microsoft.com/en-us/library/t22e924w(v=vs.80).aspx
'Programming > C++' 카테고리의 다른 글
dynamic_cast 연산자 (0) | 2014.10.26 |
---|---|
정적 바인딩(Static binding) vs. 동적 바인딩(Dynamic binding) (0) | 2014.08.19 |
RECENT COMMENT