C++ inline - 7. 클래스 내에서의 inline 함수
7. 클래스 내에서의 inline 함수
C++에서는 클래스 내부에서 정의된 멤버 함수는 자동으로 inline 함수로 처리됩니다.
따라서, 별도로 inline 키워드를 명시하지 않아도, 컴파일러는 해당 함수를 인라인 확장(Inline Expansion) 대상으로 고려합니다.
🔹 클래스 멤버 함수의 암시적 inline
✅ 암시적 inline이란?
- 클래스 내부에서 정의된 멤버 함수는 inline 키워드를 명시하지 않아도 자동으로 inline으로 간주됩니다.
- 하지만, 컴파일러가 판단하여 반드시 inline을 적용하는 것은 아님.
- 너무 큰 함수나 루프가 포함된 함수는 자동 인라인 확장이 거부될 가능성이 높음.
✅ 암시적 inline 예제
#include <iostream>
class Math {
public:
int add(int a, int b) { // 클래스 내부에서 정의 → 암시적 inline
return a + b;
}
};
int main() {
Math math;
std::cout << math.add(3, 4) << std::endl; // 함수 호출 없이 직접 연산될 가능성이 높음
return 0;
}
📌 위 코드에서 add(int a, int b)는 inline 키워드를 명시하지 않아도 inline으로 간주됨
- 클래스 내부에서 직접 정의되었으므로 암시적으로 inline이 적용됨.
- 그러나, 컴파일러가 최적화 과정에서 반드시 inline 확장을 수행하는 것은 아님.
✅ 암시적 inline이 거부될 가능성이 있는 경우
class Math {
public:
int complexOperation(int a, int b) { // 함수 크기가 커서 inline 확장 거부 가능성 높음
int result = 0;
for (int i = 0; i < 100; i++) {
result += (a * i + b);
}
return result;
}
};
📌 이 함수는 루프가 포함되어 있어 inline 확장이 거부될 가능성이 큼
- 컴파일러는 함수 크기가 너무 크거나 반복문이 많으면 inline 확장을 수행하지 않을 수 있음.
- 큰 함수는 따로 cpp 파일에서 정의하는 것이 바람직함.
🔹 헤더 파일에서 정의된 멤버 함수
✅ 헤더 파일에서 정의할 때 inline이 필요한 이유
일반적으로 클래스 멤버 함수를 헤더 파일에서 정의하면 여러 소스 파일에서 포함될 수 있음.
그러나, C++에서 동일한 함수가 여러 번 정의되면 링커 오류(Linker Error)가 발생할 수 있음.
이 문제를 방지하기 위해, 헤더 파일에서 정의된 함수에는 inline 키워드를 명시하는 것이 권장됨.
✅ 헤더 파일에서 inline 사용 예제
📁 math_utils.h
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
class Math {
public:
inline int add(int a, int b) { // 명시적 inline
return a + b;
}
inline int multiply(int a, int b) {
return a * b;
}
};
#endif // MATH_UTILS_H
📁 main.cpp
#include <iostream>
#include "math_utils.h"
int main() {
Math math;
std::cout << math.add(3, 4) << std::endl;
std::cout << math.multiply(5, 6) << std::endl;
return 0;
}
📌 이렇게 하면?
- math_utils.h를 여러 소스 파일에서 포함하더라도 링커 오류 없이 컴파일 가능.
- inline을 사용하지 않으면 다른 소스 파일에서 포함될 때 중복 정의 오류가 발생할 수 있음.
✅ 헤더 파일에서 inline을 사용하지 않으면 발생하는 문제점
📁 math_utils.h (잘못된 예)
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
class Math {
public:
int add(int a, int b); // 선언만 존재
};
#endif // MATH_UTILS_H
📁 math_utils.cpp
#include "math_utils.h"
int Math::add(int a, int b) { // 함수 정의
return a + b;
}
📁 main.cpp
#include <iostream>
#include "math_utils.h"
int main() {
Math math;
std::cout << math.add(3, 4) << std::endl;
return 0;
}
📌 이 경우 math_utils.cpp가 포함되지 않으면 링크 오류 발생
- add(int, int)의 정의가 포함되지 않아 컴파일 시 "undefined reference" 오류 발생.
- 이런 경우, 함수를 math_utils.cpp에 정의하는 것이 올바른 해결책.
- 그러나, 헤더 파일에서 정의하고 싶다면 inline을 명시하는 것이 안전함.
🔹 클래스 내 inline과 cpp 파일에서 정의하는 방법 비교
정의 방식 | 장점 | 단점 |
클래스 내부 정의 (암시적 inline) | 코드가 간결해지고 가독성이 좋음 | 코드 크기가 증가할 가능성 있음 |
헤더 파일에서 inline 사용 | 링커 오류 방지, 재사용 가능 | 많은 코드가 포함되면 컴파일 시간 증가 |
cpp 파일에서 정의 | 코드 크기 증가 방지, 모듈화 용이 | 함수 호출 오버헤드 존재 |
📌 결론
✅ 짧고 간단한 함수는 클래스 내부에서 정의하여 inline 적용
✅ 헤더 파일에서 멤버 함수를 정의할 경우 inline을 명시적으로 사용하여 링커 오류 방지
✅ 큰 함수는 cpp 파일에서 정의하여 코드 크기를 줄이고, 컴파일 시간을 최적화
📌 정리
✅ 클래스 내부에서 정의된 멤버 함수는 inline이 자동으로 적용됨 (암시적 inline)
✅ 컴파일러가 반드시 inline 확장을 수행하는 것은 아니며, 최적화 여부에 따라 결정됨
✅ 헤더 파일에서 멤버 함수를 정의하면 inline 키워드를 사용하여 링커 오류를 방지해야 함
✅ 크기가 큰 함수는 cpp 파일에서 정의하는 것이 바람직함
📌 결론
작은 함수는 inline을 활용하여 성능을 최적화할 수 있지만, 남용하면 코드 크기가 증가하고 컴파일 시간이 길어질 수 있으므로 신중하게 사용해야 합니다!