최근 수정 시각 : 2025-12-26 20:07:32

Iterator

파일:다른 뜻 아이콘.svg  
#!if 넘어옴1 != null
'''반복자'''{{{#!if 넘어옴2 == null
{{{#!if 넘어옴1[넘어옴1.length - 1] >= 0xAC00 && 넘어옴1[넘어옴1.length - 1] <= 0xD7A3
{{{#!if ((넘어옴1[넘어옴1.length - 1] - 0xAC00) % 28) == 0
는}}}{{{#!if ((넘어옴1[넘어옴1.length - 1] - 0xAC00) % 28) != 0
은}}}}}}{{{#!if 넘어옴1[넘어옴1.length - 1] < 0xAC00 || 넘어옴1[넘어옴1.length - 1] > 0xD7A3
은(는)}}}}}}{{{#!if 넘어옴2 != null
, ''''''{{{#!if 넘어옴3 == null
{{{#!if 넘어옴2[넘어옴2.length - 1] >= 0xAC00 && 넘어옴2[넘어옴2.length - 1] <= 0xD7A3
{{{#!if ((넘어옴2[넘어옴2.length - 1] - 0xAC00) % 28) == 0
는}}}{{{#!if ((넘어옴2[넘어옴2.length - 1] - 0xAC00) % 28) != 0
은}}}}}}{{{#!if 넘어옴2[넘어옴2.length - 1] < 0xAC00 || 넘어옴2[넘어옴2.length - 1] > 0xD7A3
은(는)}}}}}}}}}{{{#!if 넘어옴3 != null
, ''''''{{{#!if 넘어옴4 == null
{{{#!if 넘어옴3[넘어옴3.length - 1] >= 0xAC00 && 넘어옴3[넘어옴3.length - 1] <= 0xD7A3
{{{#!if ((넘어옴3[넘어옴3.length - 1] - 0xAC00) % 28) == 0
는}}}{{{#!if ((넘어옴3[넘어옴3.length - 1] - 0xAC00) % 28) != 0
은}}}}}}{{{#!if 넘어옴3[넘어옴3.length - 1] < 0xAC00 || 넘어옴3[넘어옴3.length - 1] > 0xD7A3
은(는)}}}}}}}}}{{{#!if 넘어옴4 != null
, ''''''{{{#!if 넘어옴5 == null
{{{#!if 넘어옴4[넘어옴4.length - 1] >= 0xAC00 && 넘어옴4[넘어옴4.length - 1] <= 0xD7A3
{{{#!if ((넘어옴4[넘어옴4.length - 1] - 0xAC00) % 28) == 0
는}}}{{{#!if ((넘어옴4[넘어옴4.length - 1] - 0xAC00) % 28) != 0
은}}}}}}{{{#!if 넘어옴4[넘어옴4.length - 1] < 0xAC00 || 넘어옴4[넘어옴4.length - 1] > 0xD7A3
은(는)}}}}}}}}}{{{#!if 넘어옴5 != null
, ''''''{{{#!if 넘어옴6 == null
{{{#!if 넘어옴5[넘어옴5.length - 1] >= 0xAC00 && 넘어옴5[넘어옴5.length - 1] <= 0xD7A3
{{{#!if ((넘어옴5[넘어옴5.length - 1] - 0xAC00) % 28) == 0
는}}}{{{#!if ((넘어옴5[넘어옴5.length - 1] - 0xAC00) % 28) != 0
은}}}}}}{{{#!if 넘어옴5[넘어옴5.length - 1] < 0xAC00 || 넘어옴5[넘어옴5.length - 1] > 0xD7A3
은(는)}}}}}}}}}{{{#!if 넘어옴6 != null
, ''''''{{{#!if 넘어옴7 == null
{{{#!if 넘어옴6[넘어옴6.length - 1] >= 0xAC00 && 넘어옴6[넘어옴6.length - 1] <= 0xD7A3
{{{#!if ((넘어옴6[넘어옴6.length - 1] - 0xAC00) % 28) == 0
는}}}{{{#!if ((넘어옴6[넘어옴6.length - 1] - 0xAC00) % 28) != 0
은}}}}}}{{{#!if 넘어옴6[넘어옴6.length - 1] < 0xAC00 || 넘어옴6[넘어옴6.length - 1] > 0xD7A3
은(는)}}}}}}}}}{{{#!if 넘어옴7 != null
, ''''''{{{#!if 넘어옴8 == null
{{{#!if 넘어옴7[넘어옴7.length - 1] >= 0xAC00 && 넘어옴7[넘어옴7.length - 1] <= 0xD7A3
{{{#!if ((넘어옴7[넘어옴7.length - 1] - 0xAC00) % 28) == 0
는}}}{{{#!if ((넘어옴7[넘어옴7.length - 1] - 0xAC00) % 28) != 0
은}}}}}}{{{#!if 넘어옴7[넘어옴7.length - 1] < 0xAC00 || 넘어옴7[넘어옴7.length - 1] > 0xD7A3
은(는)}}}}}}}}}{{{#!if 넘어옴8 != null
, ''''''{{{#!if 넘어옴9 == null
{{{#!if 넘어옴8[넘어옴8.length - 1] >= 0xAC00 && 넘어옴8[넘어옴8.length - 1] <= 0xD7A3
{{{#!if ((넘어옴8[넘어옴8.length - 1] - 0xAC00) % 28) == 0
는}}}{{{#!if ((넘어옴8[넘어옴8.length - 1] - 0xAC00) % 28) != 0
은}}}}}}{{{#!if 넘어옴8[넘어옴8.length - 1] < 0xAC00 || 넘어옴8[넘어옴8.length - 1] > 0xD7A3
은(는)}}}}}}}}}{{{#!if 넘어옴9 != null
, ''''''{{{#!if 넘어옴10 == null
{{{#!if 넘어옴9[넘어옴9.length - 1] >= 0xAC00 && 넘어옴9[넘어옴9.length - 1] <= 0xD7A3
{{{#!if ((넘어옴9[넘어옴9.length - 1] - 0xAC00) % 28) == 0
는}}}{{{#!if ((넘어옴9[넘어옴9.length - 1] - 0xAC00) % 28) != 0
은}}}}}}{{{#!if 넘어옴9[넘어옴9.length - 1] < 0xAC00 || 넘어옴9[넘어옴9.length - 1] > 0xD7A3
은(는)}}}}}}}}}{{{#!if 넘어옴10 != null
, ''''''{{{#!if 넘어옴10[넘어옴10.length - 1] >= 0xAC00 && 넘어옴10[넘어옴10.length - 1] <= 0xD7A3
{{{#!if ((넘어옴10[넘어옴10.length - 1] - 0xAC00) % 28) == 0
는}}}{{{#!if ((넘어옴10[넘어옴10.length - 1] - 0xAC00) % 28) != 0
은}}}}}}{{{#!if 넘어옴10[넘어옴10.length - 1] < 0xAC00 || 넘어옴10[넘어옴10.length - 1] > 0xD7A3
은(는)}}}}}} 여기로 연결됩니다. 
#!if 설명 == null && 리스트 == null
{{{#!if 설명1 == null
다른 뜻에 대한 내용은 아래 문서를}}}{{{#!if 설명1 != null
{{{#!html 게임 Rain World의 설정}}}에 대한 내용은 [[반복자(Rain World)]] 문서{{{#!if (문단1 == null) == (앵커1 == null)
를}}}{{{#!if 문단1 != null & 앵커1 == null
의 [[반복자(Rain World)#s-|]]번 문단을}}}{{{#!if 문단1 == null & 앵커1 != null
의 [[반복자(Rain World)#|]] 부분을}}}}}}{{{#!if 설명2 != null
, {{{#!html }}}에 대한 내용은 [[]] 문서{{{#!if (문단2 == null) == (앵커2 == null)
를}}}{{{#!if 문단2 != null & 앵커2 == null
의 [[#s-|]]번 문단을}}}{{{#!if 문단2 == null & 앵커2 != null
의 [[#|]] 부분을}}}}}}{{{#!if 설명3 != null
, {{{#!html }}}에 대한 내용은 [[]] 문서{{{#!if (문단3 == null) == (앵커3 == null)
를}}}{{{#!if 문단3 != null & 앵커3 == null
의 [[#s-|]]번 문단을}}}{{{#!if 문단3 == null & 앵커3 != null
의 [[#|]] 부분을}}}}}}{{{#!if 설명4 != null
, {{{#!html }}}에 대한 내용은 [[]] 문서{{{#!if (문단4 == null) == (앵커4 == null)
를}}}{{{#!if 문단4 != null & 앵커4 == null
의 [[#s-|]]번 문단을}}}{{{#!if 문단4 == null & 앵커4 != null
의 [[#|]] 부분을}}}}}}{{{#!if 설명5 != null
, {{{#!html }}}에 대한 내용은 [[]] 문서{{{#!if (문단5 == null) == (앵커5 == null)
를}}}{{{#!if 문단5 != null & 앵커5 == null
의 [[#s-|]]번 문단을}}}{{{#!if 문단5 == null & 앵커5 != null
의 [[#|]] 부분을}}}}}}{{{#!if 설명6 != null
, {{{#!html }}}에 대한 내용은 [[]] 문서{{{#!if (문단6 == null) == (앵커6 == null)
를}}}{{{#!if 문단6 != null & 앵커6 == null
의 [[#s-|]]번 문단을}}}{{{#!if 문단6 == null & 앵커6 != null
의 [[#|]] 부분을}}}}}}{{{#!if 설명7 != null
, {{{#!html }}}에 대한 내용은 [[]] 문서{{{#!if (문단7 == null) == (앵커7 == null)
를}}}{{{#!if 문단7 != null & 앵커7 == null
의 [[#s-|]]번 문단을}}}{{{#!if 문단7 == null & 앵커7 != null
의 [[#|]] 부분을}}}}}}{{{#!if 설명8 != null
, {{{#!html }}}에 대한 내용은 [[]] 문서{{{#!if (문단8 == null) == (앵커8 == null)
를}}}{{{#!if 문단8 != null & 앵커8 == null
의 [[#s-|]]번 문단을}}}{{{#!if 문단8 == null & 앵커8 != null
의 [[#|]] 부분을}}}}}}{{{#!if 설명9 != null
, {{{#!html }}}에 대한 내용은 [[]] 문서{{{#!if (문단9 == null) == (앵커9 == null)
를}}}{{{#!if 문단9 != null & 앵커9 == null
의 [[#s-|]]번 문단을}}}{{{#!if 문단9 == null & 앵커9 != null
의 [[#|]] 부분을}}}}}}{{{#!if 설명10 != null
, {{{#!html }}}에 대한 내용은 [[]] 문서{{{#!if (문단10 == null) == (앵커10 == null)
를}}}{{{#!if 문단10 != null & 앵커10 == null
의 [[#s-|]]번 문단을}}}{{{#!if 문단10 == null & 앵커10 != null
의 [[#|]] 부분을}}}}}}
#!if 설명 == null
{{{#!if 리스트 != null
다른 뜻에 대한 내용은 아래 문서를}}} 참고하십시오.

#!if 리스트 != null
{{{#!if 문서명1 != null
 * {{{#!if 설명1 != null
게임 Rain World의 설정: }}}[[반복자(Rain World)]] {{{#!if 문단1 != null & 앵커1 == null
문서의 [[반복자(Rain World)#s-|]]번 문단}}}{{{#!if 문단1 == null & 앵커1 != null
문서의 [[반복자(Rain World)#|]] 부분}}}}}}{{{#!if 문서명2 != null
 * {{{#!if 설명2 != null
: }}}[[]] {{{#!if 문단2 != null & 앵커2 == null
문서의 [[#s-|]]번 문단}}}{{{#!if 문단2 == null & 앵커2 != null
문서의 [[#|]] 부분}}}}}}{{{#!if 문서명3 != null
 * {{{#!if 설명3 != null
: }}}[[]] {{{#!if 문단3 != null & 앵커3 == null
문서의 [[#s-|]]번 문단}}}{{{#!if 문단3 == null & 앵커3 != null
문서의 [[#|]] 부분}}}}}}{{{#!if 문서명4 != null
 * {{{#!if 설명4 != null
: }}}[[]] {{{#!if 문단4 != null & 앵커4 == null
문서의 [[#s-|]]번 문단}}}{{{#!if 문단4 == null & 앵커4 != null
문서의 [[#|]] 부분}}}}}}{{{#!if 문서명5 != null
 * {{{#!if 설명5 != null
: }}}[[]] {{{#!if 문단5 != null & 앵커5 == null
문서의 [[#s-|]]번 문단}}}{{{#!if 문단5 == null & 앵커5 != null
문서의 [[#|]] 부분}}}}}}{{{#!if 문서명6 != null
 * {{{#!if 설명6 != null
: }}}[[]] {{{#!if 문단6 != null & 앵커6 == null
문서의 [[#s-|]]번 문단}}}{{{#!if 문단6 == null & 앵커6 != null
문서의 [[#|]] 부분}}}}}}{{{#!if 문서명7 != null
 * {{{#!if 설명7 != null
: }}}[[]] {{{#!if 문단7 != null & 앵커7 == null
문서의 [[#s-|]]번 문단}}}{{{#!if 문단7 == null & 앵커7 != null
문서의 [[#|]] 부분}}}}}}{{{#!if 문서명8 != null
 * {{{#!if 설명8 != null
: }}}[[]] {{{#!if 문단8 != null & 앵커8 == null
문서의 [[#s-|]]번 문단}}}{{{#!if 문단8 == null & 앵커8 != null
문서의 [[#|]] 부분}}}}}}{{{#!if 문서명9 != null
 * {{{#!if 설명9 != null
: }}}[[]] {{{#!if 문단9 != null & 앵커9 == null
문서의 [[#s-|]]번 문단}}}{{{#!if 문단9 == null & 앵커9 != null
문서의 [[#|]] 부분}}}}}}{{{#!if 문서명10 != null
 * {{{#!if 설명10 != null
: }}}[[]] {{{#!if 문단10 != null & 앵커10 == null
문서의 [[#s-|]]번 문단}}}{{{#!if 문단10 == null & 앵커10 != null
문서의 [[#|]] 부분}}}}}}




1. 프로그래밍 용어

반복자, 순회자 내지는 이터레이터(Iterator)는 프로그래밍에서 어떤 동작을 반복적으로 수행할 때 이용하는 방법 중 하나이다. 반복자 자체는 작업 하나의 단위가 되고, 반복자에서 작업이 끝났는지 아닌지 검사하는 동작과 작업의 결과값을 받는 동작을 지원한다.

반복자를 사용하는 방법은 여러가지가 있지만 보통 연속적인 메모리 공간에 접근할 때 사용하는 방법 중 하나로 이용된다. 이를테면 배열의 원소에 순차적으로 접근하고 싶을 때 많이 사용한다. 배열같은 연속적인 메모리 공간을 순회할 때는 보통 시작 주소를 두고 원소를 넘어갈 때마다 주소를 증감시키는 방법을 써왔다. 이때 주소 계산 법은 '배열의 시작 주소 + 오프셋(원소의 바이트 크기)'으로 결정되는데, 원소에 접근할 때는 반드시 이 과정을 거쳐야한다. 그런데 이 방법은 코딩이 복잡해지며 반복적인 Boilerplate 코드를 꾸준히 써줘야 하는 불편함이 있다. 배열의 끝을 언제나 수동으로 검사해야 한다는 문제점도 생긴다. 일반화 프로그래밍의 일환으로 반복자를 통해 주소 접근 방법을 추상화하면 계산할 필요가 없는 코드를 제거하고 언제나 일관적인 코드를 작성할 수 있다.

초기에는 처음부터 순차적으로 접근하는 전진 반복자(Forward Iterator)만 있었지만, 현재는 양방향 반복자(Bidirectional Iterator), 임의 접근 반복자(Random Access Iterator), 등 여러 가지 개념이 구현되어 있다. 그래도 제일 많이 쓰이는 전진 반복자는 대부분의 언어에서 지원한다.

C++ 표준 라이브러리의 경우 C++11부터 거의 모든 자료구조에서 상수 표현식을 지원한다. C++26에서는 벡터나 배열 말고도 std::unordered_map같은 연관 컨테이너에서도 상수 표현식을 제공한다. C++은 자료구조마다 상수 시간 내에 처리 가능한 반복자들을 제공함으로써, 언어 내에서 일관적이고 고성능의 접근 방법을 구성했다. 그런데 자료구조마다 원소를 저장하고 읽어내는 방식에 차이가 있는 탓에 제공하는 반복자 종류에 차이가 있을 수 있다. 일례로 동적 배열 클래스 std::vector<T>의 경우는 임의 접근 반복자를 지원하지만, std::list<T>는 지원하지 않고 대신 양방향 반복자를 지원한다.

1.1. 종류

반복자의 유형은 두가지가 있는데 하나는 일반적인 순회자 (Iterator) 모델, 다른 하나는 열거자 (Enumerator) 모델이다.
#!syntax cpp
class Iterator
{
public:
    T& operator*() const;
    T* operator->() const;

    bool operator==(const Iterator& other) const noexcept;

    Iterator& operator++();
    T operator++(int) const;
    Iterator& operator--();
    T operator--(int) const;

private:
    // 원본 자료구조를 가지고 있어야 함.
    std::vector<T>* _myContainer;
    size_t _myIndex;
};
순회자는 얕은 추상화 모델로서 보통 포인터와 동일한 인터페이스를 제공한다. 순회자 두개 사이의 비교를 통해 순회 종료 여부를 검증한다. 순회자는 자료구조 객체와는 별개로 존재하므로 순회자에서 참조하는 자료구조가 삭제되지 않았는지, 서로 다른 자료구조에서 받은 순회자를 쓰고 있지는 않은지, 순회자가 현재 갖고 있는 자료구조의 정보가 틀린지 아닌지를 검증해야만 한다. 그나마 쓰레기 수집을 지원하는 언어라면 큰 문제는 아니나 C++같이 수동 메모리 관리를 해야 한다면 전부다 검사해줘야 한다. 표준 라이브러리 구현체에선 다 검사를 해주지만, 만약 우리가 직접 라이브러리를 만들어야 하는 상황이라면 우리도 검사 구문을 넣어줘야 한다. 그래야 그나마 컴파일 단계에서 오류를 검출하거나 메모리 오류를 일찍 확인할 수 있다.
#!syntax csharp
List<int> list = new();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(5);

var enumerator = list.GetEnumerator();

while (enumerator.MoveNext())
{
    var value = enumerator.Current;

    Console.WriteLine(value);
}
열거자는 한번 더 추상화한 모델로서 단일한 순회자 객체 하나를 두고 자료구조를 순회한다. 이 방법은 더욱 깔끔하고 안전한 코드를 작성할 수 있다. 사용자가 신경 쓸 부분은 오로지 열거자 객체 하나에만 집중되며, 인터페이스도 통일시킬 수 있으므로 편리하다. 기본적으로 주어지는 메서드는 다음 순서가 있는 지를 확인하는 메서드[1], 다음 열거자를 가져오는 메서드[2], 그리고 값을 얻어오는 메서드[3]를 가진다. C#에서는 다음 순서로 넘어가는 메서드와 가져오는 메서드를 통일했다.

순회자 모델로 열거자를 구현할 수 있지만 내부적으로 따로 구현하는 게 성능이 잘 나온다. C++23의 <generator> 모듈은 코루틴을 써서 자료구조를 순회하는 방법을 제공한다. 이 클래스도 겉모양은 begin(), end()로 반복자를 쓰는 것 처럼 되어있지만, 사실 end()는 텅 빈 클래스 인스턴스를 반환하며 begin()에서는 코루틴의 종료 여부 및 자료구조의 말단부만 검사한다.

2. 사운드 볼텍스의 수록곡

2.1. 개요

작곡자는 yanagi로, 사용한 보컬로이드 샘플은 MEIKO와 GUMI. 곡의 분위기는 얼핏 이 곡과 닮아 있다. 좀 더 정확하게 따지자면 스코틀랜드에서 들을 수 있을 법한 음악. 이 때문인지 중간에 백파이프 음색도 들어가 있다.

2.2. 사운드 볼텍스

<colbgcolor=white,#1f2023> 사운드 볼텍스 난이도 체계
난이도 NOVICE <colcolor=orange,#dd0> ADVANCED <colcolor=red> EXHAUST
자켓 파일:external/p.eagate.573.jp/1n0007_iterator_yanagi_jacket_n.jpg 파일:external/p.eagate.573.jp/1n0007_iterator_yanagi_jacket_a.jpg 파일:external/p.eagate.573.jp/1n0007_iterator_yanagi_jacket_e.jpg
레벨 02 09 11
체인 수 0530 0710 0885
일러스트 담당 XTC
이펙터 レッドホットスクリューズ しばまる子 レッドホットスクリューズ
수록 시기 BOOTH 02(2012.1.18)
BPM 130

변경점
2013/06/05ADV 패턴 난이도 상승(06 → 07)
2014/11/20ADV 패턴 난이도 상승(07 → 08)
  • SKILL ANALYZER 수록
    • ADVANCED : Skill Level 02(2013.9.5 ~ 2013.10.4, 2015.4.1 ~ 2015.5.29)


EXH 손배치 포함 PERFECT영상

EXH 패턴은 엇박 투성이, 10레벨 치고는 PUC가 매우 어렵다. 박자 자체가 cloud 비슷하게 난해해 개인차가 상당히 갈린다.

사운드 볼텍스 나블라에서 11레벨로 승격되었다.


ADV 손배치 포함 PERFECT영상

유비트에 Jumping Boogie가 있다면 사볼에는 Iterator가 있다고 과언이 아닐 정도의 이빨빠진 박자를 자랑한다!

ADV 패턴은 1/6박 숏노트(!)의 함정도 있어서, 초창기에는 6이라는 사기 난이도를 자랑했다. 이 때문에 6레벨 주제에 폭사한 사람도 많아 원성을 많이 샀다. 물론 이것은 순전히 박자 탓, 박자에만 익숙해지면 PUC도 노릴만하다. 그런데 그게 큰 문제라서 2013년 9월 기준으로도 클리어 레이트가 60%를 밑돌고 있다. (다른 예는 Broken ADV) 그리고 스킬 애널라이저에 스킬 레벨 02의 마지막 곡으로 들어갔는데, 세 곡중 이 곡만 7레벨. 따라서 스킬 레벨 02를 따려는 유저들에겐 엇박의 쓴맛을 보여줬다. 결국 II에서 올라갔던 레벨이 III에서 또 올라가 2번의 레벨업 달성. IV에서는 그대로 8레벨로 정착했지만, PUC 난이도 만큼은 여전히 8레벨 최상급이다.
사운드 볼텍스 나블라에서 한 번 더 승격되었다.

NOV 패턴은 위 두 패턴에 비하면 평범하지만, 후살의 왼쪽 FX버튼을 잡고 R노브를 돌리는 패턴은 요주의.
[1] 주로 HasNext[2] 주로 GetNext[3] 주로 GetValue