> For the complete documentation index, see [llms.txt](https://byulseop-til.gitbook.io/sinheeseop_til/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://byulseop-til.gitbook.io/sinheeseop_til/c++/101/cpp_define_vs_final_static.md).

# DefineVsFinalStatic

* 상수 정의가 필요할 때
* 재사용성이 좋습니다. (이식성과 유지보수성이 좋다는 소리와 같습니다)
  * 유지 보수성 : 여러 파일 간에 공통으로 사용되는 값을 중앙집중적으로 관리 가능합니다.
* 컴파일 전에 소스 코드를 유연하게 조작 할 필요가 있었습니다.

  * 예시 : 조건부 컴파일이 가능함

  ```cpp
  #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`과의 차이점

* **실행 방식**:
  * **C++의 `#define`**:
    * 전처리 단계에서 텍스트 치환이 이루어지므로, 런타임에 별도의 메모리 할당 없이 코드에 직접 삽입됩니다.
  * **자바의 `static final`**:
    * 클래스의 멤버 변수로서 런타임에 상수 풀 혹은 클래스 정적 데이터 영역에 할당되어, JVM이 관리합니다. 단, 컴파일 타임 상수인 경우 인라인 최적화가 일어날 수 있습니다.
* **타입 검사**:
  * \*`#define`\*은 단순 텍스트 치환이므로 타입 안전성이 없고, 컴파일러가 타입을 확인하지 않습니다.
  * \*`static final`\*은 명시적인 타입 선언으로, 컴파일러가 타입 검사를 수행합니다.
* **디버깅 및 유지보수**:
  * \*`#define`\*은 전처리 후 소스 코드에 직접 보이지 않기 때문에, 디버깅 시에 원래의 매크로가 어떻게 치환되었는지 확인하기 어려울 수 있습니다.
  * \*`static final`\*은 클래스의 일부로 존재하기 때문에, 디버깅 시에도 상수의 값과 타입을 쉽게 확인할 수 있습니다.
