switch는 무엇을 위한 것인가
switch는 하나의 값을 고정된 선택지 목록과 비교하여 일치하는 분기를 실행합니다. 같은 변수를 서로 다른 상수와 계속 비교하는 긴 if/else if 체인을 쓰고 있는 자신을 발견했다면, switch가 그 의도를 더 명확하게 표현하며, 종종 더 빠른 점프 테이블로 컴파일됩니다.
switch는 정수에 가까운 값에 대해 컴파일 타임 상수와의 동등 비교만 수행합니다. 범위를 검사하거나, 문자열을 비교하거나, 조건을 결합할 수는 없습니다. 그런 경우에는 if/else를 유지하세요.
기본 switch
switch에 값을 주고, 관심 있는 값마다 case 레이블을 나열합니다. 각 분기는 break로 끝납니다.
값 3은 case 3:에 일치하므로 "Wednesday"가 출력되고 break가 switch 밖으로 빠져나갑니다. default 분기는 모든 것을 받아내는 분기로, 어떤 case도 일치하지 않을 때 실행됩니다. 선택 사항이지만, 모든 값이 처리된다고 확신하지 못한다면 포함하세요.
case 레이블은 조건이 아니라 콜론이 뒤따르는 단순한 상수임에 유의하세요. case 3:라고 쓰며, case day == 3:라고는 절대 쓰지 않습니다.
break와 폴스루
이것은 C++에서 switch의 가장 중요한 함정입니다. 어떤 case가 일치한 뒤, 실행은 다음 case에서 멈추지 않습니다. break나 닫는 중괄호를 만날 때까지 곧장 계속 실행됩니다. break 문이 빠지면 어떤 일이 일어나는지 봅시다.
"one"만 나올 거라 예상할 수도 있습니다. 하지만 네 줄이 모두 출력됩니다. case 1:에 일치하면 거기서 switch에 진입한 다음, 그 아래의 모든 레이블을 통과해 흘러내려갑니다. 각 분기 뒤에 break;를 추가하면 원하던 한 줄만 얻게 됩니다. break를 빠뜨리는 것은 "왜 내 switch가 코드를 너무 많이 실행하지?"라는 버그의 고전적인 원인입니다.
case를 그룹화하기 위한 의도적 폴스루
폴스루가 항상 실수인 것은 아닙니다. 여러 case가 하나의 본문을 공유하게 하는 관용적인 방법입니다. case를 비워 두면(문도 없고 break도 없이) 모두 다음 블록으로 흘러 들어갑니다.
'A', 'B', 'C'는 모두 같은 "Pass" 줄에 도달합니다. 처음 두 case가 비어 있어 세 번째로 폴스루하기 때문입니다. 이는 깔끔하고 의도된 것입니다. 어떤 코드를 실행한 뒤에 의도적으로 폴스루하려 할 때는 주석으로 문서화하세요. 또는 C++17 이상에서는 [[fallthrough]]; 속성을 사용하면 컴파일러에게 "네, 의도한 겁니다"라고 알리고 폴스루 경고를 잠재울 수 있습니다.
enum에 대한 switch
switch는 enum과 자연스럽게 어울립니다. enum은 정확히 "고정된 값 집합 중 하나"이기 때문입니다. 게다가 컴파일러는 열거자 중 하나를 처리하는 것을 잊으면 경고해 줄 수 있습니다.
범위 지정 enum class에서는 각 레이블을 한정해야 합니다(Direction::East). 모든 열거자가 다뤄지므로 default는 필요 없습니다. 그리고 많은 컴파일러는 나중에 다섯 번째 방향을 추가하고 그 case를 추가하는 것을 잊으면 경고해 줍니다. 이러한 컴파일러의 도움은 enum에 대해 if/else 체인보다 switch를 선호하는 큰 이유입니다.
함정: case 안에서의 선언
한 case 안에서 초기화자를 가진 변수를 선언하고, 범위를 지정하지 않은 채 다른 case들에 걸쳐 보이게 할 수는 없습니다. 이는 흔한 컴파일 오류입니다.
switch (x) {
case 1:
int n = 10; // 오류: case 2로 점프하면 이 초기화를 건너뛴다
cout << n;
break;
case 2:
cout << "two";
break;
}
컴파일러가 이를 거부하는 이유는, case 2:로 흘러 들어가면 n이 아직 범위 안에 있는데도 n의 초기화를 건너뛰게 되기 때문입니다. 해결책은 case 본문을 자체 중괄호로 감싸 변수에 전용 블록을 주는 것입니다.
case가 자체 지역 변수를 필요로 할 때는 언제든 중괄호를 붙이세요. 이는 변수가 아래 case들로 새어 나가는 것도 막아 줍니다.
다음: for 반복문
switch와 if는 프로그램이 어떤 코드를 한 번 실행할지 선택하게 해 줍니다. 하지만 많은 작업은 같은 일을 여러 번 하는 것을 의미합니다. 세기, 리스트를 순회하기, 조건이 바뀔 때까지 반복하기 등이죠. for 반복문은 그 일을 위한 일꾼이며, 다음 페이지입니다.
자주 묻는 질문
C++에서 if-else 대신 switch를 언제 써야 하나요?
메뉴 선택, 요일 번호, enum처럼 정수에 가까운 하나의 값을 여러 개의 고정된 상수 선택지와 비교할 때 switch를 사용하세요. 긴 if/else if 사다리보다 읽기 쉽고, 컴파일러가 분기를 최적화할 수 있게 해 줍니다. 조건이 범위(x > 10), 부동소수점 값, 문자열, 여러 변수를 다룰 때는 if/else를 유지하세요. switch는 그중 어느 것도 할 수 없습니다.
C++ switch 문에서 break가 왜 필요한가요?
어떤 case가 일치하면, C++은 break나 switch의 끝에 도달할 때까지 그 다음 case들을 계속 실행합니다. 이를 폴스루(fall-through)라고 합니다. break가 이를 멈춥니다. break를 빠뜨리는 것은 고전적인 버그입니다. case 1:에 일치했는데 실수로 case 2, case 3, default의 코드까지 실행하게 되죠.
C++에서 어떤 타입에 대해 switch할 수 있나요?
정수 타입이나 열거형 타입만 가능합니다. int, char, short, long, bool, 범위 지정/비범위 enum, 그리고 그중 하나로 변환되는 모든 것입니다. double, float, std::string에는 switch할 수 없습니다. 그런 경우에는 if/else를 사용하세요. 각 case 레이블은 컴파일 타임 상수여야 합니다.