C++ 프로그래밍

C++ 헤더파일에 선언할 수 있는 4가지 타입의 전역변수

하늘흐늘 2009. 4. 21. 21:07
반응형

최근에 헤더파일에서의 static 전역변수에 대한 포스트를 올렸다 지웠습니다. 생각지도 못한 버그를 만나 2시간이나 고생을 했기 때문이었는데, C/C++에서의 static 키워드는 여러모로 조심스러운 키워드인거 같습니다. 멀티쓰레드에서의 버그가능성까지... 이 글은 덕분에 테스트해 본 전역변수에 대하여 요약하여 놓은 것입니다. 참고로 테스트 환경은 Visual Studio 2008 sp1 입니다.

object라는 클래스가 있다는 가정하에 헤더파일에 선언할 수 있는 4가지 타입의 전역변수는 아래와 같습니다.
	1. object var;
	2. static object var;
	3. extern object var; //object var;라고 특정 cpp파일에 정의되어 있다고 가정합니다.
	4. typedef Singleton < object >  var; //Singleton이라는 템플릿이 정의되어 있다고 가정합니다. 
1번과 같은 경우 2개 이상의 cpp파일에서 해당 헤더파일을 포함하는 경우, 변수가 미리 정의되어 있다는 에러를 발생시킵니다. 즉, 1개의 cpp파일을 위해서만 정의할 수 있는, 단순히 cpp파일에 선언한 것을 헤더파일로 옮긴거 외에는 의미를 가지지 않습니다. 뭐랄까? 1개의 cpp파일을 위한 전역변수가 되겠죠.

2번과 같은 경우 2개 이상의 cpp파일에서 해당 변수를 사용할 수 있습니다. 쥔장도 처음에는 무지 편해서 좋아했죠. 덕분에 버그 잡느라 2시간이상 헤메였습니다. 왜냐하면 헤더파일을 포함한 cpp파일의 개수만큼 객체가 생성되기 때문입니다. 전역변수기는 한데 각각의 cpp파일마다 각각의 전역변수가 생성됩니다. 뭐, 좀 더 정확하게 표현하자면 헤더파일을 포함하는 각각의 cpp파일에서만 사용하는 로컬변수라고 부를 수 있겠죠. 쥔장이 용어에서 헷갈리는 이유는 변수의 생존 범위인데, 쥔장의 개념에서 지역변수의 개념은 함수안에서만 존재하는 변수를 지역변수라고 생각했기 때문입니다. 그리고는 단순하게 로컬변수가 아닌 변수는 전역변수라고 생각했기 때문에... (흠... 지금도 헷갈림...켁~)

3번과 같은 경우는 cout, cin과 같은 우리가 흔희 보는 STL의 전역변수들이 사용하는 기법입니다. 진정으로 여러 cpp파일에서 공유하는 한개의 전역변수가 생성됩니다. 즉, C/C++에서 전역변수라고 불리는 것은 3번과 같은 경우가 될 것입니다.

4번과 같은 경우는 Design Pattern의 하나로서 1개의 객체만을 생성하게 됩니다. 전역변수의 개념이나 3번과 같이 compiler에 의해서가 아닌 테크닉에 의하여 생성되게 됩니다. 실제적으로는 클래스의 typedef이며 var::Instance() 와 같이 클래스의 static함수를 사용하여 1개의 전역변수를 사용하게 됩니다.

쥔장이 헤멘 이유는 아무생각없이 2번 방법을 썼기 떄문입니다. 정석으로 배우면 우리는 3번과 4번만을 사용하게 되며 어느정도 초급을 넘어서면 global object와 Singlton의 차이에 대해서 생각하게 됩니다. 패턴주의자라면 4번을 선호할 것이며 C에서 부터 C++로 넘어오신 분이면 3번을 선호할 것 입니다.

초급을 넘어서면 심심할 때 고민할 이 둘의 차이에 대해서 말하자면 구글형이 가르켜준 Singleton VS global object 라는 토론에 잘 나와 있습니다. 인상깊었던 내용의 일부를 이야기하자면 표면적으로 비슷하지만 Singleton 쪽이 좀 깔끔하게 정의할 수 있고 (extern은 특정 cpp파일에서 실제 객체의 정의해야 하며, 전역객체가 많아지면 특정 객체의 정의 위치를 찾는 것도 한 일 되겠죠?) 그 외에 config파일 사용, 늦은 초기화 등의 테크닉을 사용할 수 있다는 장점이 있습니다. 개인적으로 그 외의 차이점은 전역변수 같은 경우는 전역변수를 다루는 메모리에 들어가는데 비하여 Singleton은 생성된 객체가 힙메모리에 위치하는 차이점이 있는듯 보입니다.


반응형