Range-based
for
loop
(since C++11)
범위에 대해 for 루프를 실행합니다.
범위 기반 for 루프는 값의 범위(예: 컨테이너의 모든 요소)에서 동작하는 전통적인 for loop 보다 더 가독성이 높은 대안으로 사용됩니다.
목차구문
설명위 구문은 다음 코드와 동등한 코드를 생성합니다 (임시 객체의 수명 확장을 제외하고 range-initializer 의 경우 아래 참조 ) (C++23부터) ( /* */ 로 감싸인 변수와 표현식은 설명 목적으로만 사용됨):
range-initializer 는 반복할 시퀀스나 범위를 초기화하기 위해 평가됩니다. 시퀀스의 각 요소는 차례로 역참조되어 item-declaration 에 지정된 타입과 이름을 가진 변수를 초기화하는 데 사용됩니다. item-declaration 은 다음 중 하나일 수 있습니다:
설명 전용 표현식 /* begin-expr */ 과 /* end-expr */ 은 다음과 같이 정의됩니다:
루프가 statement 내에서 종료되어야 하는 경우, break statement 를 종료 문으로 사용할 수 있습니다. 현재 반복을 statement 내에서 종료해야 하는 경우, continue statement 를 단축키로 사용할 수 있습니다. init-statement 에서 도입된 이름이 statement 의 가장 바깥쪽 블록에서 재선언되면 프로그램의 형식이 올바르지 않습니다: for (int i : {1, 2, 3}) int i = 1; // 오류: 재선언 임시 범위 초기화자만약 range-initializer 가 임시 객체를 반환하면, 해당 객체의 수명은 포워딩 참조 /* range */ 에 바인딩됨으로써 루프가 끝날 때까지 확장됩니다. range-initializer 내의 모든 임시 객체들의 수명은 연장되지 않습니다 해당 임시 객체들이 range-initializer 끝에서 파괴되는 경우가 아닌 한 (C++23부터) . // foo()가 값으로 반환하는 경우 for (auto& x : foo().items()) { /* ... */ } // C++23까지 미정의 동작
참고 사항만약 range-initializer 가 braced-enclosed initializer list 인 경우, /* range */ 는 std::initializer_list 에 대한 참조로 추론됩니다. 제네릭 코드에서는 전달 참조에 대해 추론을 사용하는 것이 안전하며, 사실상 바람직합니다, for ( auto && var : sequence ) .
멤버 해석은 범위 타입이 "
item-declaration 에서 선언된 변수는 일반적으로 statement 에서 사용되지만, 이를 반드시 사용해야 하는 것은 아닙니다.
복사 시 쓰기(copy-on-write) 의미론을 가진 (non-const) 객체와 함께 사용될 때, 범위 기반
for
루프는 (암묵적으로) non-const
키워드예제
이 코드 실행
#include <iostream> #include <vector> int main() { std::vector<int> v = {0, 1, 2, 3, 4, 5}; for (const int& i : v) // const 참조로 접근 std::cout << i << ' '; std::cout << '\n'; for (auto i : v) // 값으로 접근, i의 타입은 int std::cout << i << ' '; std::cout << '\n'; for (auto&& i : v) // 전달 참조로 접근, i의 타입은 int& std::cout << i << ' '; std::cout << '\n'; const auto& cv = v; for (auto&& i : cv) // 전달 참조로 접근, i의 타입은 const int& std::cout << i << ' '; std::cout << '\n'; for (int n : {0, 1, 2, 3, 4, 5}) // 초기화자는 중괄호로 둘러싸인 // 초기화자 리스트일 수 있음 std::cout << n << ' '; std::cout << '\n'; int a[] = {0, 1, 2, 3, 4, 5}; for (int n : a) // 초기화자는 배열일 수 있음 std::cout << n << ' '; std::cout << '\n'; for ([[maybe_unused]] int n : a) std::cout << 1 << ' '; // 루프 변수를 사용하지 않아도 됨 std::cout << '\n'; for (auto n = v.size(); auto i : v) // 초기화문 (C++20) std::cout << --n + i << ' '; std::cout << '\n'; for (typedef decltype(v)::value_type elem_t; elem_t i : v) // typedef 선언을 초기화문으로 사용 (C++20) std::cout << i << ' '; std::cout << '\n'; for (using elem_t = decltype(v)::value_type; elem_t i : v) // 별칭 선언을 초기화문으로 사용 (C++23) std::cout << i << ' '; std::cout << '\n'; } 출력: 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 1 1 1 1 1 1 5 5 5 5 5 5 0 1 2 3 4 5 0 1 2 3 4 5 결함 보고서다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
참고
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||