본문 바로가기
programing/C++

인라인 함수와 템플릿

by RedWiz 2017. 1. 25.

- 인라인 함수

> 대체적으로 헤더 파일에 들어 있어야 함

> 대부분의 빌드 환경에서 인라인을 컴파일 도중에 수행하기 때문

> 인라인 함수 호출을 그 함수의 본문으로 바꿔치기 하려면, 일단 컴파일러는 그 함수가 어떤 형태인지 알고 있어야함

(물론, 링크  도중에 인라인을 수행하는 빌드 환경도 있음 ex) 닷넷 공통 언어 내부 구조(Common Language Infrastructure : CLI)에 기반한 닷넷 관리 환경(예외일 뿐, 규칙에는 포함 안됨))


- 템플릿

> 대체적으로 헤더 파일에 들어있어야 함

> 템플릿이 사용되는 부분에서 해당 템플릿을 인스턴스로 만드려면 그것이 어떻게 생겼는지 컴파일러가 알아야 하기 때문

(인라인 함수와 마찬가지로 이 부분도 모두 그런 것은 아님. 어떤 빌드 환경은 링크 도중에 템플릿 인스턴스화를 수행하기도 함. 그렇지만 대세는 컴파일 타임 인스턴스화)


- 템플릿 인스턴스화는 인라인과 별개로 완전히 관련이 없음

> 어떤 템플릿을 만들고 있는데 이 템플릿으로부터 만들어지는 모든 함수가 인라인 함수로 하고 싶으면 그 템플릿에 inline을 붙여 선언하면 됨

> 만들고 있는 함수 템플릿이 굳이 인라인 될 이유가 없다면 그 템플릿을 인라인 함수로 선언하지 않아도 됨


- 인라인은 분명 비용(코드 비대화)을 동반하는 동작이며 아무렇지 않게 일어나도록 내버려 둬도 괜찮지 않음


- 인라인은 컴파일러 선에서 무시 할 수 있는 요청. 대부분의 컴파일러의 경우, 아무리 인라인 함수로 선언 되어 있어도 자신이 보기에 복잡한 함수는 절대로 인라인 확장의 대상에 넣지 않고 정말 간단한 함수라도 가상 함수 호출은 절대 인라인하지 않음

> 루프가 있다거나 재귀 함수인 경우 복잡하다고 판단

> virtual의 의미가 어떤 함수를 호출 할 지 결정하는 작업을 실행 중에 한다 라는 뜻

> inline의 의미가 함수 호출 위치에 후출할 함수를 끼워 넣는 작업을 프로그램 실행 전에 한다는 뜻

> 주어진 시점에서 호출 할 함수가 무엇이 될지를 컴파일러도 알 수 없으면 어찌 할 수 없음


- 인라인 함수가 실제로 인라인을 결정은 개발자가 사용하는 빌드 환경에 달려 있으며 그 중 컴파일러의 결정을 따름


- 요청한 함수에 대한 인라인이 실패 했을 경우, 경고 메시지를 내주는 진단 수준 설정 기능이 대부분 컴파일러에 들어 있음.


- 완벽한 인라인 조건을 갖추어도 어떻게 호출하느냐에 따라 인라인이 되기도 하고 안 되기도 함

> ex. 인라인 함수의 주소를 취하는 코드


- 인라인이 되지 않는 인라인 함수는 함수 포인터를 전혀 사용하지 않아도 컴파일러가 인라인으로 선언된 생성자 및 소멸자에 대해 아웃라인 함수 본문을 만들 수도 있음.

> 객체 원소 배열을 사용할 경우 배열을 구성하는 객체들을 생성하고 소멸시킬 때 생성자/소멸자의 함수 포인터를 얻어내려면 함수 본문이 반드시 필요함.


- C++는 객체가 생성되고 소멸될 때 일어나는 일들에 대해 여러가지 보장을 준비해 놓음

> new를 하면 동척으로 만들어지는 객체를 생성자가 자동으로 초기화 해 주고 delete를 하면 이에 대응되는 소멸자가 호출됨.

> 어떤 객체를 생성하면 그 객체의 기본 클래스 부분과 그 객체의 데이터 멤버들이 자동으로 생성되며, 그 객체가 소멸될 때 이에 반대되는 순서로 소멸과정이 저절로 이루어지는 것도 마찬가지.

> C++는 객체가 생성되는 도중 예외가 던져지더라도, 이미 생성이 완료된 부분 만큼은 자동으로 말끔히 소멸되도록 보장.


- C++는 무엇을 해야 하는지는 정해 두었지만 그것을 어떻게 해야 하는지는 정하지 않음. 이 부분은 컴파일러 구현자에게 달려 있으며 자기들이 스스로 일어나지 않음.

> 눈에 보이지 않지만 이런 일을 가능하게 하는 어떤 코드가 프로그램에 포함되어야 하고, 이 코드(컴파일러가 만들어서 컴파일 도중에 소스 코드에 삽입하는 코드)가 소스 코드 어딘가에 들어가 있어야 한다는 결론이 나오며, 때에 따라서는 소스 코드가 들어가 있는 장소가 생성자와 소멸자일 수 도 있음.

> 상속 관계에서 inline 생성자를 만들다보면 부모와 자식마다, 멤버 객체마다 코드가 만들어져서 비대해 질 수 있음.


- 있지도 않는 함수에 중단점을 걸어야 하기 때문에, 대부분의 디버거가 무척이나 곤란해 함

> 아무것도 인라인 하지 말아야 함.

> 혹은, 꼭 인라인 해야 하는 함수 혹은 정말 단순한 함수에 한해서만 인라인 함수로 선언하는 것으로 시작해야 함.

> 인라인을 주의 해서 사용하는 버릇을 들여서, 디버깅하고 싶은 부분에서 디버거를 제대로 쓸 수 있도록 만들고 정말 필요한 위치에 인라인 함수를 놓도록하여 수동 최적화를 해야 함.


'programing > C++' 카테고리의 다른 글

포인터  (0) 2017.02.17
DLL 사용시 내부 함수 목록 확인 및 lib 생성, 명시적 연결  (0) 2017.02.01
음성 채팅 구현  (0) 2017.01.20
[Modern C++] RValue Reference  (0) 2016.12.29
exit(), assert(), 에러처리  (0) 2016.12.27