DefineVsFinalStatic
상수 정의가 필요할 때
재사용성이 좋습니다. (이식성과 유지보수성이 좋다는 소리와 같습니다)
유지 보수성 : 여러 파일 간에 공통으로 사용되는 값을 중앙집중적으로 관리 가능합니다.
컴파일 전에 소스 코드를 유연하게 조작 할 필요가 있었습니다.
예시 : 조건부 컴파일이 가능함
#include <iostream> #define DEBUG // 이 줄을 주석 처리하면 Release 모드로 동작합니다. int main() { #ifdef DEBUG std::cout << "Debug mode" << std::endl; #else std::cout << "Release mode" << std::endl; #endif return 0; }
장점
메모리 효율성:
전처리 단계에서 리터럴로 치환되므로 런타임에 추가 메모리 할당 없이 값이 직접 코드에 삽입됩니다.
💡
간단한 설명
자바의 경우 멤버 변수의 값을 재사용 할 때, 새로운 변수에 담아서 재사용하는 경우 그만큼의 메모리가 추가됨
define 은 전처리 단계에서 호출이 아닌 진짜 코드 자체를 해당 텍스트로 변경하기 때문에 재사용시 추가 메모리를 차지하지 않음.
추가로 define 으로 정의된 함수의 경우 스택 프레임 생성, 반환 주소 저장등의 오버헤드가 줄어듬.
컴파일 타임 최적화:
상수 값이 코드에 직접 삽입되므로 함수 호출 오버헤드 없이 빠르게 사용할 수 있습니다.
유지보수 용이성:
상수 값이나 반복되는 코드 조각을 한 곳에서 관리할 수 있어, 변경 시 여러 부분을 일일이 수정할 필요 없이 한 번에 수정 가능합니다.
조건부 컴파일:
#ifdef
,#ifndef
등을 사용하여 플랫폼별 또는 상황별로 코드를 선택적으로 컴파일할 수 있습니다.
단점
타입 검사 없음:
단순 텍스트 치환이기 때문에, 타입 안전성이 보장되지 않습니다. (예를 들어, 잘못된 타입의 값이 삽입될 수 있음)
디버깅 어려움:
전처리 단계에서 치환되어 소스 코드에는 원래
#define
문이 보이지 않으므로, 디버깅 시에 실제 치환된 코드 추적이 어려울 수 있습니다.
예측 불가능한 부작용:
복잡한 매크로는 치환 과정에서 예상치 못한 결과를 초래할 수 있고, 코드 유지보수 시 혼란을 줄 수 있습니다.
자바의 static final
과의 차이점
static final
과의 차이점실행 방식:
C++의
#define
:전처리 단계에서 텍스트 치환이 이루어지므로, 런타임에 별도의 메모리 할당 없이 코드에 직접 삽입됩니다.
자바의
static final
:클래스의 멤버 변수로서 런타임에 상수 풀 혹은 클래스 정적 데이터 영역에 할당되어, JVM이 관리합니다. 단, 컴파일 타임 상수인 경우 인라인 최적화가 일어날 수 있습니다.
타입 검사:
*
#define
*은 단순 텍스트 치환이므로 타입 안전성이 없고, 컴파일러가 타입을 확인하지 않습니다.*
static final
*은 명시적인 타입 선언으로, 컴파일러가 타입 검사를 수행합니다.
디버깅 및 유지보수:
*
#define
*은 전처리 후 소스 코드에 직접 보이지 않기 때문에, 디버깅 시에 원래의 매크로가 어떻게 치환되었는지 확인하기 어려울 수 있습니다.*
static final
*은 클래스의 일부로 존재하기 때문에, 디버깅 시에도 상수의 값과 타입을 쉽게 확인할 수 있습니다.
Last updated