KoreanFoodie's Study
Effective C++ | 항목 30 : 인라인 함수는 미주알고주알 따져서 이해해 두자 본문
Tutorials/C++ : Advanced
Effective C++ | 항목 30 : 인라인 함수는 미주알고주알 따져서 이해해 두자
GoldGiver 2022. 10. 25. 16:26
C++ 프로그래머의 필독서이자 바이블인, 스콧 마이어스의 Modern Effective C++ 를 읽고 기억할 내용을 요약하고 있습니다. 꼭 읽어보시길 추천드립니다!
항목 30 : 인라인 함수는 미주알고주알 따져서 이해해 두자
핵심 :
1. 함수 인라인은 작고, 자주 호출되는 함수에 대해서만 하자. 이렇게 하면 디버깅 및 라이브러리의 바이너리 업그레이드가 용이해지고, 자칫 생길 수 있는 코드 부풀림 현상이 최소화되며, 프로그램의 속력이 더 빨라질 수 있는 여지가 최고로 많아진다.
2. 함수 템플릿이 대개 헤더 파일에 들어간다는 일반적인 부분만 생각해서 이들을 inline 으로 선언하면 안 된다.
인라인 함수를 사용하면 컴파일러가 함수 본문에 대해 문맥별(context-specific) 최적화를 걸기가 용이해진다. 목적 코드의 크기도 작아지며 명령어 캐시 적중률도 높아진다.
inline 은 컴파일러에 대해 '요청'을 하는 것이지, '명령' 이 아니다. 즉, inline 을 붙이지 않아도 그냥 되는 경우도 있고 명시적으로 할 수도 있다는 뜻이다. 암시적인 inline 의 예시를 보자.
class Person
{
public:
...
// age 는 클래스 정의 내부에서 정의됨
int age() const { return theAge; }
private:
int theAge;
};
대부분의 경우, inline 함수는 컴파일 도중에 수행하므로 헤더 파일에 넣어주는 것이 좋다. 하지만 복잡한 함수나 가상함수는 인라인해 주지 않는다. 다음 예시들을 보면서, 인라인이 될 수 있는 경우와 아닌 경우를 살펴보자.
// f 의 호출은 컴파일러가 인라인해 준다고 가정
inline void f() { ... }
// pf 는 f 를 가리키는 함수 포인터
void (*pf)() = f;
...
// 이 함수는 인라인화 될 것임
f();
// 이 함수는 인라인화되지 않음
// 함수 포인터를 통해 호출되고 있으므로!
pf();
생성자와 소멸자도 인라인화하기에 그리 좋지 않은 함수이다. 다음의 예를 보자.
class Base
{
private:
std::string bm1, bm2;
};
class Derived: public Base
{
public:
// Derived 생성자가 비어 있다
// 정말 비어 있을까?
Derived() {}
private:
std::string dm1, dm2, dm3;
};
위의 Derived 생성자는 비어 있는 것처럼 보이지만, 실제로는 아래와 같이 동작할 것이다(실제 코드가 저렇게 생성된다는 뜻은 아니다).
class Derived: public Base
{
public:
// Derived 생성자가 비어 있다
// 정말 비어 있을까?
Derived()
{
Base::Base();
// dm1 생성을 시도
try { dm1.std::string::string(); }
// dm1 생성 도중 예외를 던지면?
// 기본 클래스 부분 소멸 후 예외 전파
catch (...)
{
Base::~Base();
throw;
}
// dm2, dm3 에 대해서도 위와 동일
}
private:
std::string dm1, dm2, dm3;
};
그렇다면 어떤 함수를 인라인으로 선언해야 하고 어떤 것을 선언하지 말아야 할까?
우선, 아무것도 인라인하지 말자. 아니면 정말 단순한 함수만 인라인화를 하자. 만약 f 라는 특정 함수가 인라인화 되어 있고, 해당 함수를 이용한 응용 프로그램을 만들었다고 가정하자. 만약 나중에 이 함수를 바꾸면, 이 함수를 이용한 모든 프로그램을 다시 컴파일 해야 한다. 하지만 인라인이 아니라면, 링크만 해주면 되므로 비용이 훨씬 덜 들게 될 것이다!
'Tutorials > C++ : Advanced' 카테고리의 다른 글
Effective C++ | 항목 32 : public 상속 모형은 반드시 "is-a(...는 ...의 일종이다)"를 따르도록 만들자 (0) | 2022.10.25 |
---|---|
Effective C++ | 항목 31 : 파일 사이의 컴파일 의존성을 최대로 줄이자 (0) | 2022.10.25 |
Effective C++ | 항목 29 : 예외 안전성이 확보되는 그날 위해 싸우고 또 싸우자! (0) | 2022.10.25 |
Effective C++ | 항목 28 : 내부에서 사용하는 객체에 대한 '핸들'을 반환하는 코드는 되도록 피하자 (0) | 2022.10.25 |
Effective C++ | 항목 27 : 캐스팅은 절약, 또 절약! 잊지 말자 (0) | 2022.10.25 |
Comments