C++ Default Parameter - 5. 주의사항 및 Best Practice

2025. 3. 27. 13:34프로그래밍 언어/C++

✅ 5. 주의사항 및 Best Practice


📌 1. 기본 인자 변경이 미치는 영향

기본 인자는 컴파일 타임에 값이 삽입되므로, 기본값 변경은 모든 호출 코드의 의미를 바꿀 수 있습니다.

// 초기 버전
void connect(int port = 3306);
connect();  // port = 3306

// 변경 후
void connect(int port = 5432);
connect();  // port = 5432 ← 호출 코드는 같지만 동작이 변경됨

⚠️ 기본 인자 값은 함수 호출 시점이 아닌 함수 선언 시점 기준으로 적용되므로,
기본값 변경은 API 변경 수준으로 간주하고 신중히 관리해야 합니다.


📌 2. Header 파일에 기본 인자를 작성할 때의 위험성

✅ 중복 정의 문제

헤더에 기본 인자가 포함된 함수를 여러 소스 파일에서 include하면,
링크 타임에 중복 정의 오류가 발생할 수 있습니다.

✅ 선언부와 정의부의 불일치

// header.h
void foo(int x = 1);

// foo.cpp
void foo(int x = 2);  // ❌ 정의부와 선언부가 다름 → 예기치 않은 동작
  • 컴파일러는 선언부의 기본 인자만 사용합니다.
  • 정의부의 값은 무시되며, 실수로 값이 달라도 경고만 뜨고 오류가 발생하지 않을 수 있음.

✅ 다중 포함 시 링크 오류

  • #pragma once 또는 #ifndef-#define 등의 include guard 필수
  • 기본 인자를 포함하는 함수 선언은 하나의 헤더에만 작성

✅ 정의부에서는 기본 인자를 생략하는 것이 원칙입니다.


📌 3. 포인터/참조 타입 기본 인자 사용 시 유의사항

전달 방식 안전한 기본값 예시 주의 사항
포인터 nullptr new로 할당된 객체는 누수 위험
참조 전역 변수, 정적 변수 임시 객체, 지역 변수는 사용 불가

❌ 잘못된 예:

void print(int* ptr = new int(5));  // ❌ 메모리 누수 발생 가능성

int& ref = 10;  // ❌ 임시 객체 참조 불가

✅ 포인터에는 nullptr,
✅ 참조에는 유효한 전역 또는 정적 객체만 사용해야 안전합니다.


📌 4. 유지보수 Best Practice

항목 권장 방식
기본 인자 위치 오른쪽(끝)부터 순차적으로 지정
선언/정의 분리 시 선언부에만 기본값 작성, 정의부는 생략
값 변경 가능성 있는 기본값 상수(const) 또는 설정 함수로 분리
포인터/참조 타입 기본값 안전한 값 사용, 위험한 동적 할당 지양
복잡한 기본값 함수 내부에서 조건문으로 처리
팀 프로젝트 시 일관성 유지 코딩 컨벤션으로 기본 인자 사용 방식 통일 권장

✅ 예시: 유지보수에 강한 설계

const int DefaultPort = 3306;
void connect(std::string host = "localhost", int port = DefaultPort);

📌 5. 코드 리뷰 체크리스트 ✅

기본 인자를 사용하는 코드를 리뷰할 때 다음 항목을 점검하세요:

  • 기본 인자는 오른쪽부터 지정되었는가?
  • 선언부(헤더)에만 기본 인자가 작성되었는가?
  • 기본값이 컴파일 타임에 평가 가능한가?
  • 포인터/참조 타입의 기본값이 안전한가?
  • 기본 인자 변경 시 영향 범위가 명확히 고려되었는가?
  • 기본값이 하드코딩 되어 있지 않은가? (→ 상수 분리 권장)
  • 오버로딩과 혼용 시 호출 모호성 문제가 없는가?

📌 6. 버전 관리 시 주의점

항목 주의사항
기본 인자 변경 API 동작이 바뀌므로 버전 변경 간 주의 필요
외부 라이브러리 제공 시 기본 인자를 변경할 경우 반드시 릴리스 노트에 명시
백워드 호환성 유지가 필요할 때 오버로딩으로 대체하거나 새로운 함수 이름 사용 고려

예시:

// 이전 버전
void download(int timeout = 3);

// 이후 버전
void download(int timeout = 5);  // → 호출 코드는 같지만 동작은 달라짐!

✅ 변경이 필요한 경우, 기존 버전은 유지한 채 오버로딩 또는 새 함수 이름 제공도 고려할 수 있습니다.


📌 7. 컴파일러별 차이점

컴파일러 차이 가능성 예시
A 컴파일러 중복 정의 시 경고는 없지만, 링크 오류 발생 가능
B 컴파일러 비교적 명확한 경고 메시지 제공
C 컴파일러 선언과 정의의 기본값 불일치 시 조용히 무시될 수 있음

🔎 기본 인자는 컴파일 타임 개념이기 때문에,
다중 플랫폼 개발 시에는 반드시 GCC, Clang, MSVC 모두 테스트하는 것이 안전합니다.


📌 8. 핵심 요약표

항목 요약
기본 인자 변경 영향 모든 호출부 동작 변경 가능성 → 주의
헤더 작성 시 유의사항 선언부만 작성, include guard 필수
포인터/참조 타입 기본값 안전한 값만 사용, 동적 할당 지양
유지보수 전략 상수화, 정의부 생략, 내부 조건 처리 권장
코드 리뷰 체크 항목 총 7가지 핵심 확인 포인트
버전 관리 시 위험 요소 기본 인자 값 변경은 API 변경과 유사한 영향
컴파일러별 차이점 경고/오류 해석, 중복 정의 처리 방식이 다름