오늘의 코드카타
순위
- 플로이드-워샬 알고리즘을 통한 노드 간의 승리-패배 계산
-> 문제 풀이
오늘의 공부
학습한 강의
- 챕터 4
- 게임플레이 프레임워크
- 멀티플레이 디버그 로깅과 이벤트 함수
정리 노트
오늘의 CS
C++에서 4가지 캐스팅 방법
- C++에서는 타입 변환을 안전하고 명확하게 하기 위해서 4가지 캐스팅 연산자를 제공함
1. static_cast
- 컴파일 타임에 타입을 변환
- 서로 관련 있는 타입 간 변환 (ex. 기본형 변환, 상속 관계 포인터/레퍼런스 변환)
- 안전성 보장하지 않음 (런타임 타입 체크 없음 -> 잘못된 다운캐스팅도 허용)
2. dynamic_cast
- 런타임 타입 체크(RTTI) 기반 변환
- 주로 다운캐스팅(부모->자식)에서 사용
- 변환 불가능하면 포인터는
nullptr 반환, 레퍼런스는 bad_cast 예외 발생
- 가상 함수 테이블이 있는 클래스(다형성)에서만 사용 가능
3. const_cast
const 속성을 제거하거나 추가
- 포인터/레퍼런스에만 사용 가능
- 원래 const로 선언된 객체를 강제로 수정하면 UB(정의되지 않은 동작) 발생
-> const로 선언된 객체는 컴파일러가 절대 수정하지 않을 것을 전제로 최적화하기 때문에 수정하면 안 됨
-> 원래 const가 아니었던 객체에서만 안전
4. reinterpret_cast
- 비트 단위 재해석 (low-level 변환)
- 서로 전혀 관계없는 포인터 타입 간 변환 가능
- 매우 위험 -> 하드웨어/메모리 접근, 네트워크 패킷 해석 등에 사용
C 스타일 캐스팅
(T)expr : 혼합된 위험한 변환
- 단점
- 의도가 불분명
- 실패를 감지할 방법이 없음 -> 실패 시
nullptr로 반환해주지 않음 -> 런타임 UB 가능
- 너무 많은 걸 "몰래" 해버림 ->
const 제거나 비트 재해석까지 시도
기본형 변환
- 의미 :
int, float, double, char 같은 기본 자료형 간 변환
- 암묵적 변환도 가능
double d = 3; // int -> double
- 기본형 변환은 안전할 수도 있지만, 데이터 손실 가능성이 존재
UB (Undefined Behavior)
- C++에서 표준이 보장하지 않는 동작
- UB가 발생하면 결과가 예측 불가능 (컴파일러/플랫폼/최적화에 따라 달라짐)
- 대표적인 UB 예시
- 잘못된 메모리 접근 - 널 포인터 역참조
- 할당 해제 후 접근 - 댕글링 포인터
- 배열 범위 초과
- int 오버플로우
- 잘못된 캐스팅
업캐스팅 vs 다운캐스팅
- 업캐스팅
- 자식 클래스 -> 부모 클래스로의 형 변환
- 암시적으로 허용됨 ->
static_cast 없이도 가능
- 부모 클래스 포인터/참조로 자식을 가리킬 수 있음
- 안전한 캐스팅
- 다운캐스팅
- 부모 클래스 -> 자식 클래스로의 형 변환
- 암시적으로는 불가능 ->
static_cast 또는 dynamic_cast 필요
- 위험할 수 있음 -> 부모 포인터가 실제로 자식 객체를 가리키지 않는다면 UB 발생
- 정적 캐스팅 (
static_cast)
- 컴파일러는 단순히 형 변환만 수행 -> 실제 객체 타입은 체크하지 않음
- 잘못된 경우 UB 발생
- 동적 캐스팅 (
dynamic_cast)
- RTTI(Run-time Type Information)를 이용해 실제 타입 검사
- 실패하면
nullptr 반환
- 안전하지만 약간의 런타임 비용 발생