본문으로 건너뛰기

안동민 개발노트

본문 시작

break와 continue

break로 가장 안쪽 대상 반복을 종료하고 continue로 현재 반복만 건너뛰는 정확한 도착 지점과 안전 점검 기준을 구분합니다.

반복 도중 더 이상 탐색할 필요가 없거나 현재 항목만 제외해야 한다면 제어를 다음 순차 문장보다 앞쪽으로 옮길 수 있습니다.

이 장에서 다루는 일반 제어문을 기준으로 break는 자신을 둘러싼 반복문 또는 switch 문 가운데 가장 안쪽 문을 끝내고, continue는 자신을 둘러싼 가장 안쪽 반복문의 반복 계속 지점으로 이동합니다. continueswitch 자체를 대상으로 하지 않습니다.

두 문장은 모두 남은 문장을 무조건 건너뛰는 점프이므로, 키워드보다 대상 문장, 실제 도착 지점, 그 사이에 생략되는 작업을 함께 읽어야 합니다.

C++의 break가 가장 안쪽 반복문 또는 switch를 끝내고 continue가 반복문 종류별 반복 계속 지점으로 이동하는 규칙과 중첩 switch 및 반복문에서의 대상을 비교한 표

C++ · JUMP TARGET CONTRACT

키워드보다 둘러싼 문장과 도착 지점을 먼저 읽습니다. break는 대상 문장을 끝내고, continue는 현재 반복의 남은 본문을 건너뜁니다. 가장 안쪽의 적격 문장이 실제 제어 이동을 결정합니다.

이 장에서 다루는 일반 반복문과 switch의 점프 도착 지점
실행 경로 대상이 되는 문장 건너뛰는 범위 다음 실행
break 가장 안쪽 반복문 또는 switch 대상 문장의 나머지; 반복이면 남은 횟수 끝난 문장 바로 다음
continue · while 가장 안쪽 while 현재 본문의 남은 문장 조건 검사
continue · do 가장 안쪽 do 반복 현재 본문의 남은 문장 본문 뒤 조건 검사
continue · for 가장 안쪽 고전 for 현재 본문의 남은 문장 반복식, 그다음 조건
continue · 범위 for 가장 안쪽 범위 반복 현재 원소의 남은 처리 반복자 증가, 그다음 조건

break · 대상 종료

가장 안쪽 반복문 또는 switch → 그 문장 다음

현재 본문의 나머지뿐 아니라 대상 반복의 남은 횟수도 실행하지 않습니다.

continue · 현재 반복 생략

가장 안쪽 반복문의 반복 계속 지점

switchcontinue의 대상이 아닙니다.

while · do

while은 다음 조건으로, do 반복은 본문 뒤 조건으로 이어집니다.

고전·범위 for

고전 형식은 반복식을, 범위 형식은 반복자 증가를 거친 뒤 조건을 다시 검사합니다.

반복문 안의 switch

while (ready()) {
  switch (kind()) {
    case stop: break;    // switch만 종료
    case skip: continue; // while 조건으로
  }
  work();
}

break는 더 가까운 switch를 선택하지만, continue는 바깥 반복문을 선택합니다.

중첩 반복문

두 키워드 모두 가장 안쪽의 적격 대상 하나를 선택

C++에는 여러 반복을 이름으로 지정해 한 번에 끝내는 labeled break 문법이 없습니다. 여러 단계 종료는 함수 분리·상태 전달 같은 구조로 의도를 드러냅니다.

이 도표는 이 장의 일반 반복문과 switch를 다룹니다. 최신 초안의 expansion statement 같은 별도 문법까지 일반화하지 않습니다.

break 문: 루프 즉시 종료

먼저 가장 안쪽의 대상 문장을 완전히 끝낼지, 현재 반복의 나머지만 건너뛸지 구분합니다.

break 문은 자신을 둘러싼 반복문 또는 switch 문 가운데 가장 안쪽 문을 종료하고, 그 문 바로 다음으로 제어를 옮깁니다.

break 문이 실행되는 순간 선택된 대상 문장의 나머지는 건너뛰어집니다. 대상이 반복문이면 남은 반복 전체가 끝나고, 대상이 switch이면 그 switch만 끝납니다.

반복문 안에 switch가 중첩되어 있다면 switch 안의 break는 바깥 반복문이 아니라 switch만 끝냅니다.

사용 목적
  • 특정 조건이 충족되었을 때 더 이상 반복할 필요가 없을 경우.
  • 무한 루프 내에서 특정 조건에 따라 루프를 안전하게 탈출할 경우.
  • switch 문에서 한 case 블록의 실행을 마친 후 다른 case로 넘어가는 fall-through를 방지할 경우 (지난 장에서 학습).
예시 1: 1부터 10까지 출력하다가 5가 되면 종료
#include <iostream>

int main() {
    std::cout << "1부터 10까지 출력 (5에서 break):" << std::endl;
    for (int i = 1; i <= 10; ++i) {
        if (i == 5) {
            std::cout << "5가 되어 루프 종료!" << std::endl;
            break; // i가 5가 되면 for 루프를 즉시 종료
        }
        std::cout << i << " ";
    }
    std::cout << "\n루프 밖으로 나왔습니다." << std::endl;
    /* 출력:
    1 2 3 4 5가 되어 루프 종료!
    루프 밖으로 나왔습니다.
    */
    return 0;
}
예시 2: 사용자 입력을 받아 음수 입력 시 루프 종료
#include <iostream>
#include <limits>

int main() {
    int num;
    while (true) { // 무한 루프
        std::cout << "0 이상의 정수를 입력하세요 (음수를 입력하면 종료): ";

        if (!(std::cin >> num)) {
            if (std::cin.eof()) {
                std::cout << "\n입력이 종료되었습니다." << std::endl;
                break;
            }

            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cout << "정수를 입력해야 합니다." << std::endl;
            continue;
        }

        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

        if (num < 0) {
            std::cout << "음수가 입력되어 입력 루프를 종료합니다." << std::endl;
            break; // 음수가 입력되면 while 루프를 즉시 종료
        }
        std::cout << "입력하신 값: " << num << std::endl;
    }
    std::cout << "입력 루프 다음 문장을 실행합니다." << std::endl;

    return 0;
}

중첩 루프에서의 break: break 문은 자신을 둘러싼 반복문 또는 switch 문 가운데 가장 안쪽 문 하나만 종료합니다.

여러 단계의 반복을 함께 끝내야 한다면 의도를 드러내는 상태 플래그를 바깥 반복에서도 검사하거나, 탐색을 별도 함수로 분리해 return으로 그 함수 전체를 끝내는 구조를 사용할 수 있습니다. C++에는 여러 반복을 지정해 한 번에 끝내는 labeled break 문법이 없습니다.

예시 3: 중첩 루프에서의 break
#include <iostream>

int main() {
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            if (i == 1 && j == 1) {
                std::cout << "내부 루프 break!" << std::endl;
                break; // 이 break는 안쪽 for (j 루프)만 종료시킴
            }
            std::cout << "i: " << i << ", j: " << j << std::endl;
        }
        std::cout << "외부 루프 (i: " << i << ") 계속 진행 중" << std::endl;
    }
    /* 출력:
    i: 0, j: 0
    i: 0, j: 1
    i: 0, j: 2
    외부 루프 (i: 0) 계속 진행 중
    i: 1, j: 0
    내부 루프 break!
    외부 루프 (i: 1) 계속 진행 중 // 외부 루프는 계속 실행됨
    i: 2, j: 0
    i: 2, j: 1
    i: 2, j: 2
    외부 루프 (i: 2) 계속 진행 중
    */
    return 0;
}

continue 문: 현재 반복 건너뛰기

continue 문은 현재 반복 몸체의 나머지 부분을 건너뛰고, 자신을 둘러싼 가장 안쪽 반복문의 반복 계속 지점으로 제어를 옮깁니다.

실제 도착 지점은 반복문 종류에 따라 다릅니다. whiledo-while은 조건 검사로, 고전 for는 반복식 실행 후 조건 검사로, 범위 기반 for는 다음 원소를 위한 반복자 증가 후 조건 검사로 이어집니다. 반복문 안에 switch가 있어도 switchcontinue의 대상이 아닙니다.

사용 목적
  • 특정 조건이 충족되었을 때 현재 반복을 중단하고 다음 반복으로 넘어가야 할 경우.
  • 특정 데이터를 처리할 수 없거나, 유효하지 않아 건너뛰고 다음 데이터로 넘어갈 경우.
예시 1: 1부터 10까지의 짝수만 출력
#include <iostream>

int main() {
    std::cout << "1부터 10까지의 짝수만 출력:" << std::endl;
    for (int i = 1; i <= 10; ++i) {
        if (i % 2 != 0) { // i가 홀수이면
            continue; // 현재 반복 건너뛰고 다음 i 값으로 넘어감
        }
        std::cout << i << " "; // 홀수일 때는 이 코드가 실행되지 않음
    }
    std::cout << "\n루프가 완료되었습니다." << std::endl;
    /* 출력:
    2 4 6 8 10
    루프가 완료되었습니다.
    */
    return 0;
}
예시 2: 0으로 나누는 경우 건너뛰기
#include <iostream>

int main() {
    int numbers[] = {10, 5, 0, 8, 2}; // 배열 요소
    for (int num : numbers) { // 범위 기반 for 문
        if (num == 0) {
            std::cout << "0이 발견되어 나눗셈을 건너뜁니다." << std::endl;
            continue; // 현재 num이 0이므로 이 반복을 건너뛰고 다음 요소로
        }
        std::cout << "100 / " << num << " = " << (100 / num) << std::endl;
    }
    /* 출력:
    100 / 10 = 10
    100 / 5 = 20
    0이 발견되어 나눗셈을 건너뜁니다.
    100 / 8 = 12
    100 / 2 = 50
    */
    return 0;
}

while/do-while 문에서의 continue 주의사항: while 또는 do-while 문에서 continue가 사용될 때, 루프를 종료시키는 조건 변수의 증감(또는 변경)이 continue 이후에 있다면 문제가 발생할 수 있습니다.

continue가 실행되면 조건 변수 변경 코드가 건너뛰어지기 때문에 무한 루프에 빠질 위험이 있습니다.

예시 3: while 문에서의 continue 주의사항
#include <iostream>

int main() {
    int count = 0;
    while (count < 5) {
        if (count == 2) {
            std::cout << "Count 2를 건너뜁니다." << std::endl;
            continue; // !주의! count++가 실행되지 않아 무한 루프!
        }
        std::cout << "Current count: " << count << std::endl;
        count++; // 이 부분이 continue 때문에 건너뛰어질 수 있음
    }
    /* 출력:
    Current count: 0
    Current count: 1
    Count 2를 건너뜁니다.
    Count 2를 건너뜁니다.
    Count 2를 건너뜁니다.
    ... (무한 반복)
    */
    return 0;
}

위 예시에서 count가 2가 되면 continue가 실행되어 count++가 건너뛰어집니다.

count는 계속 2인 상태로 남아 while (count < 5) 조건이 항상 참이 되어 무한 루프에 빠집니다.

이런 경우에는 continue 전에 count++를 수행하거나, if 조건 자체를 재구성해야 합니다.

예시 4: while 문에서의 continue 올바른 사용
#include <iostream>

int main() {
    int count = 0;
    while (count < 5) {
        count++; // 조건을 변경하는 코드를 continue보다 먼저 두거나,
        if (count == 3) { // 3을 건너뛰는 예시 (이전 2를 건너뛰는 예시와 다름)
            std::cout << "Count 3을 건너뜁니다." << std::endl;
            continue;
        }
        std::cout << "Current count: " << count << std::endl;
    }
    /* 출력:
    Current count: 1
    Current count: 2
    Count 3을 건너뜁니다.
    Current count: 4
    Current count: 5
    */
    return 0;
}

breakcontinue의 사용 시점

  • break: 루프를 완전히 중단하고 싶을 때. 즉, 더 이상 루프 내의 어떤 반복도 필요 없을 때.
  • continue: 현재 반복은 중단하지만, 루프 자체는 계속해서 다음 반복을 진행하고 싶을 때.

두 문장 모두 아래쪽의 갱신, 결과 반영, 로그, 수동 정리 호출을 건너뛸 수 있습니다. 점프로 블록을 벗어날 때 이미 생성된 자동 저장 기간 객체는 역순으로 파괴되지만, 코드 아래에 직접 적어 둔 release() 같은 호출까지 자동 실행되는 것은 아닙니다. 자원 수명은 RAII 객체로 표현하고, 제어문 아래에 반드시 실행되어야 하는 수동 정리를 두지 않습니다.

조건 분기가 많아 정상 흐름을 찾기 어렵다면 조건식을 재구성하거나 탐색·처리를 별도 함수 또는 표준 알고리즘으로 나누는 편이 더 명확할 수 있습니다.

C++ 반복문에서 break와 continue가 건너뛰는 상태 갱신, 결과 반영, 수동 정리 코드를 감사하고 자동 객체의 파괴와 여러 단계 종료 구조를 구분하는 안전 점검표

C++ · SKIPPED WORK AUDIT

점프 사이에 생략되는 작업이 반복의 안전성을 결정합니다. 도착 지점만 맞아도 충분하지 않습니다. 진행 상태, 결과 반영, 관측, 자원 수명이 모든 경로에서 유지되는지 확인합니다.

위험 · 갱신을 건너뛰는 continue

std::size_t index = 0;
while (index < items.size()) {
  if (!valid(items[index])) continue;
  use(items[index]);
  ++index;
}

유효하지 않은 항목에서는 index가 변하지 않아 같은 조건과 원소를 다시 만납니다.

안전 · 반복 계속 지점이 갱신을 보장

for (std::size_t index = 0;
     index < items.size(); ++index) {
  if (!valid(items[index])) continue;
  use(items[index]);
}

continue 뒤에도 고전 for의 반복식이 실행되므로 다음 인덱스로 진행합니다.

  1. 대상 문장을 표시한다

    중첩 반복과 switch 가운데 실제로 가장 안쪽에 있는 적격 대상을 찾습니다.

  2. 반복 계속 지점을 표시한다

    while·do의 조건, 고전 for의 반복식, 범위 for의 반복자 증가를 구분합니다.

  3. 생략되는 부수 효과를 나열한다

    상태 갱신, 결과 저장, 로그, 커밋, 수동 release()가 점프 아래에 있지 않은지 확인합니다.

  4. 자원 수명은 RAII로 분리한다

    점프로 범위를 벗어나면 생성된 자동 객체는 역순으로 파괴됩니다. 그러나 아래쪽의 수동 정리 호출은 건너뛸 수 있으므로 객체 수명으로 정리를 표현합니다.

  5. 여러 단계 종료는 구조로 드러낸다

    바깥 반복까지 끝내야 한다면 상태를 전달하거나 탐색을 함수로 분리해 return합니다. 한 개의 break가 여러 반복을 끝내지는 않습니다.

breakcontinue는 자원 관리 기법이 아닙니다. 모든 제어 경로에서 유지돼야 하는 불변식과 수명을 먼저 설계하고, 점프는 가까운 조건에서 의도를 드러내는 데 사용합니다.